The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2345 lines
97KB

  1. # ==============================================================================
  2. #
  3. # This file is part of the JUCE library.
  4. # Copyright (c) 2022 - Raw Material Software Limited
  5. #
  6. # JUCE is an open source library subject to commercial or open-source
  7. # licensing.
  8. #
  9. # By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  10. # Agreement and JUCE Privacy Policy.
  11. #
  12. # End User License Agreement: www.juce.com/juce-7-licence
  13. # Privacy Policy: www.juce.com/juce-privacy-policy
  14. #
  15. # Or: You may also use this code under the terms of the GPL v3 (see
  16. # www.gnu.org/licenses).
  17. #
  18. # JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  19. # EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  20. # DISCLAIMED.
  21. #
  22. # ==============================================================================
  23. # ==================================================================================================
  24. # JUCE Target Support Helper Functions
  25. #
  26. # In this file, functions intended for use by end-users have the prefix `juce_`.
  27. # Functions beginning with an underscore should be considered private and susceptible to
  28. # change, so don't call them directly.
  29. #
  30. # See the readme at `docs/CMake API.md` for more information about CMake usage,
  31. # including documentation of the public functions in this file.
  32. # ==================================================================================================
  33. include_guard(GLOBAL)
  34. cmake_minimum_required(VERSION 3.22)
  35. define_property(TARGET PROPERTY JUCE_COMPANY_NAME INHERITED
  36. BRIEF_DOCS "The company name for a particular target"
  37. FULL_DOCS "This can be found in ProjectInfo::companyName in a generated JuceHeader.h")
  38. set_property(GLOBAL PROPERTY JUCE_COMPANY_NAME "yourcompany")
  39. define_property(TARGET PROPERTY JUCE_COMPANY_WEBSITE INHERITED
  40. BRIEF_DOCS "The company website for a particular target"
  41. FULL_DOCS "This will be placed in the Info.plist for the target")
  42. set_property(GLOBAL PROPERTY JUCE_COMPANY_WEBSITE "")
  43. define_property(TARGET PROPERTY JUCE_COMPANY_EMAIL INHERITED
  44. BRIEF_DOCS "The company email address for a particular target"
  45. FULL_DOCS "This will be placed in the Info.plist for the target")
  46. set_property(GLOBAL PROPERTY JUCE_COMPANY_EMAIL "")
  47. define_property(TARGET PROPERTY JUCE_COMPANY_COPYRIGHT INHERITED
  48. BRIEF_DOCS "The company copyright for a particular target"
  49. FULL_DOCS "This will be placed in the Info.plist for the target")
  50. set_property(GLOBAL PROPERTY JUCE_COMPANY_COPYRIGHT "")
  51. define_property(TARGET PROPERTY JUCE_VST_COPY_DIR INHERITED
  52. BRIEF_DOCS "Install location for VST2 plugins"
  53. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  54. define_property(TARGET PROPERTY JUCE_VST3_COPY_DIR INHERITED
  55. BRIEF_DOCS "Install location for VST3 plugins"
  56. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  57. define_property(TARGET PROPERTY JUCE_AU_COPY_DIR INHERITED
  58. BRIEF_DOCS "Install location for AU plugins"
  59. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  60. define_property(TARGET PROPERTY JUCE_AAX_COPY_DIR INHERITED
  61. BRIEF_DOCS "Install location for AAX plugins"
  62. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  63. define_property(TARGET PROPERTY JUCE_UNITY_COPY_DIR INHERITED
  64. BRIEF_DOCS "Install location for Unity plugins"
  65. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  66. define_property(TARGET PROPERTY JUCE_LV2_COPY_DIR INHERITED
  67. BRIEF_DOCS "Install location for LV2 plugins"
  68. FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
  69. define_property(TARGET PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD INHERITED
  70. BRIEF_DOCS "Whether or not plugins should be copied after building"
  71. FULL_DOCS "Whether or not plugins should be copied after building")
  72. set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE)
  73. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  74. _juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl)
  75. _juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0)
  76. endif()
  77. # We set up default/fallback copy dirs here. If you need different copy dirs, use
  78. # set_directory_properties or set_target_properties to adjust the values of `JUCE_*_COPY_DIR` at
  79. # the appropriate scope.
  80. function(_juce_set_default_properties)
  81. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  82. set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/LV2")
  83. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST")
  84. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3")
  85. set_property(GLOBAL PROPERTY JUCE_AU_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components")
  86. set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Unity")
  87. set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "/Library/Application Support/Avid/Audio/Plug-Ins")
  88. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  89. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  90. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{ProgramW6432}/Steinberg/Vstplugins")
  91. set(prefix "$ENV{CommonProgramW6432}")
  92. else()
  93. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{programfiles\(x86\)}/Steinberg/Vstplugins")
  94. set(prefix "$ENV{CommonProgramFiles\(x86\)}")
  95. endif()
  96. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "${prefix}/VST3")
  97. set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "${prefix}/Avid/Audio/Plug-Ins")
  98. set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{APPDATA}/LV2")
  99. set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{APPDATA}/Unity")
  100. elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  101. set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{HOME}/.lv2")
  102. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/.vst")
  103. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/.vst3")
  104. set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{HOME}/.unity")
  105. endif()
  106. endfunction()
  107. _juce_set_default_properties()
  108. # ==================================================================================================
  109. function(juce_add_bundle_resources_directory target folder)
  110. _juce_make_absolute(folder)
  111. if(NOT EXISTS "${folder}")
  112. message(FATAL_ERROR "Could not find resource folder ${folder}")
  113. endif()
  114. get_filename_component(folder_parent_path "${folder}" DIRECTORY)
  115. file(GLOB_RECURSE resources RELATIVE "${folder_parent_path}" "${folder}/*")
  116. foreach(file IN LISTS resources)
  117. target_sources(${target} PRIVATE "${folder_parent_path}/${file}")
  118. get_filename_component(resource_parent_path "${file}" DIRECTORY)
  119. set_source_files_properties("${folder_parent_path}/${file}" PROPERTIES
  120. HEADER_FILE_ONLY TRUE
  121. MACOSX_PACKAGE_LOCATION "Resources/${resource_parent_path}")
  122. endforeach()
  123. endfunction()
  124. # ==================================================================================================
  125. function(_juce_create_linux_subprocess_helper_target)
  126. if(TARGET juce_linux_subprocess_helper)
  127. return()
  128. endif()
  129. set(source "${JUCE_CMAKE_UTILS_DIR}/juce_LinuxSubprocessHelper.cpp")
  130. add_executable(juce_linux_subprocess_helper ${source})
  131. add_executable(juce::juce_linux_subprocess_helper ALIAS juce_linux_subprocess_helper)
  132. target_compile_features(juce_linux_subprocess_helper PRIVATE cxx_std_17)
  133. set(THREADS_PREFER_PTHREAD_FLAG ON)
  134. find_package(Threads REQUIRED)
  135. target_link_libraries(juce_linux_subprocess_helper PRIVATE Threads::Threads ${CMAKE_DL_LIBS})
  136. endfunction()
  137. function(_juce_create_embedded_linux_subprocess_target output_target_name target)
  138. # This library needs to be created in every directory where a target wants to link against it.
  139. # Pre CMake 3.20 the GENERATED property is only visible in the directory of the current target,
  140. # and even post 3.20, CMake will not know how to generate the sources outside this directory.
  141. set(target_directory_key JUCE_EMBEDDED_LINUX_SUBPROCESS_TARGET)
  142. get_directory_property(embedded_linux_subprocess_target ${target_directory_key})
  143. if(embedded_linux_subprocess_target)
  144. set(${output_target_name} juce::${embedded_linux_subprocess_target} PARENT_SCOPE)
  145. return()
  146. endif()
  147. set(prefix "_juce_directory_prefix")
  148. set(embedded_linux_subprocess_target ${prefix}_embedded_linux_subprocess)
  149. while(TARGET ${embedded_linux_subprocess_target})
  150. set(embedded_linux_subprocess_target ${prefix}_${embedded_linux_subprocess_target})
  151. endwhile()
  152. _juce_create_linux_subprocess_helper_target()
  153. get_target_property(generated_sources_directory ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  154. if(generated_sources_directory)
  155. set(juce_linux_subprocess_helper_binary_dir "${generated_sources_directory}")
  156. else()
  157. set(juce_linux_subprocess_helper_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/juce_LinuxSubprocessHelper")
  158. endif()
  159. set(binary_header_file "${juce_linux_subprocess_helper_binary_dir}/juce_LinuxSubprocessHelperBinaryData.h")
  160. set(binary_source_file "${juce_linux_subprocess_helper_binary_dir}/juce_LinuxSubprocessHelperBinaryData.cpp")
  161. set(juceaide_input_file "${juce_linux_subprocess_helper_binary_dir}/input_file_list")
  162. file(GENERATE OUTPUT ${juceaide_input_file} CONTENT "$<TARGET_FILE:juce_linux_subprocess_helper>")
  163. file(MAKE_DIRECTORY ${juce_linux_subprocess_helper_binary_dir})
  164. add_custom_command(
  165. OUTPUT
  166. ${binary_header_file}
  167. ${binary_source_file}
  168. COMMAND juce::juceaide binarydata "LinuxSubprocessHelperBinaryData" "${binary_header_file}"
  169. ${juce_linux_subprocess_helper_binary_dir} "${juceaide_input_file}"
  170. COMMAND
  171. ${CMAKE_COMMAND} -E rename "${juce_linux_subprocess_helper_binary_dir}/BinaryData1.cpp" "${binary_source_file}"
  172. WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  173. DEPENDS juce_linux_subprocess_helper
  174. VERBATIM)
  175. add_library(${embedded_linux_subprocess_target} INTERFACE)
  176. target_sources(${embedded_linux_subprocess_target} INTERFACE ${binary_source_file})
  177. target_include_directories(${embedded_linux_subprocess_target} INTERFACE ${juce_linux_subprocess_helper_binary_dir})
  178. target_compile_definitions(${embedded_linux_subprocess_target} INTERFACE JUCE_USE_EXTERNAL_TEMPORARY_SUBPROCESS=1)
  179. add_library(juce::${embedded_linux_subprocess_target} ALIAS ${embedded_linux_subprocess_target})
  180. set_directory_properties(PROPERTIES ${target_directory_key} ${embedded_linux_subprocess_target})
  181. set(${output_target_name} juce::${embedded_linux_subprocess_target} PARENT_SCOPE)
  182. endfunction()
  183. function(juce_link_with_embedded_linux_subprocess target)
  184. _juce_create_embedded_linux_subprocess_target(embedded_linux_subprocess_target ${target})
  185. target_link_libraries(${target} PRIVATE ${embedded_linux_subprocess_target})
  186. endfunction()
  187. # ==================================================================================================
  188. # Ideally, we'd check the preprocessor defs on the target to see whether
  189. # JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off,
  190. # and then link libraries as appropriate.
  191. # Unfortunately, this doesn't work, because linking a new library (curl/webkit/StoreKit)
  192. # updates the target's compile defs, which results in a recursion/circular-dependency.
  193. # Instead, we ask the user to explicitly request curl/webkit/StoreKit linking if they
  194. # know they need it. Otherwise, we won't link anything.
  195. # See the NEEDS_CURL, NEEDS_WEB_BROWSER, and NEEDS_STORE_KIT options in the CMake/readme.md.
  196. function(_juce_link_optional_libraries target)
  197. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  198. get_target_property(needs_curl ${target} JUCE_NEEDS_CURL)
  199. if(needs_curl)
  200. target_link_libraries(${target} PRIVATE juce::pkgconfig_JUCE_CURL_LINUX_DEPS)
  201. endif()
  202. get_target_property(needs_browser ${target} JUCE_NEEDS_WEB_BROWSER)
  203. if(needs_browser)
  204. target_link_libraries(${target} PRIVATE juce::pkgconfig_JUCE_BROWSER_LINUX_DEPS)
  205. get_target_property(is_plugin ${target} JUCE_IS_PLUGIN)
  206. if(is_plugin)
  207. juce_link_with_embedded_linux_subprocess(${target})
  208. endif()
  209. endif()
  210. elseif(APPLE)
  211. get_target_property(needs_storekit ${target} JUCE_NEEDS_STORE_KIT)
  212. if(needs_storekit)
  213. _juce_link_frameworks("${target}" PRIVATE StoreKit)
  214. endif()
  215. get_target_property(needs_camera ${target} JUCE_CAMERA_PERMISSION_ENABLED)
  216. if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND needs_camera)
  217. _juce_link_frameworks("${target}" PRIVATE ImageIO)
  218. endif()
  219. endif()
  220. endfunction()
  221. # ==================================================================================================
  222. function(_juce_get_module_definitions target filter out_var)
  223. set(compile_defs $<TARGET_GENEX_EVAL:${target},$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>>)
  224. if(filter)
  225. set(${out_var} $<FILTER:${compile_defs},EXCLUDE,JucePlugin_Build_|JUCE_SHARED_CODE> PARENT_SCOPE)
  226. else()
  227. set(${out_var} ${compile_defs} PARENT_SCOPE)
  228. endif()
  229. endfunction()
  230. function(_juce_append_record output key)
  231. string(ASCII 30 RS)
  232. string(ASCII 31 US)
  233. set(${output} "${${output}}${key}${US}${ARGN}${RS}" PARENT_SCOPE)
  234. endfunction()
  235. function(_juce_append_target_property output key target property)
  236. get_target_property(prop ${target} ${property})
  237. if(prop STREQUAL "prop-NOTFOUND")
  238. set(prop)
  239. endif()
  240. _juce_append_record(${output} ${key} ${prop})
  241. set(${output} "${${output}}" PARENT_SCOPE)
  242. endfunction()
  243. # This is all info that should be known at configure time (i.e. no generator expressions here!)
  244. # We use this info to generate plists and entitlements files, also at configure time.
  245. function(_juce_write_configure_time_info target)
  246. _juce_append_target_property(file_content EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME)
  247. _juce_append_target_property(file_content VERSION ${target} JUCE_VERSION)
  248. _juce_append_target_property(file_content BUILD_VERSION ${target} JUCE_BUILD_VERSION)
  249. _juce_append_target_property(file_content PLIST_TO_MERGE ${target} JUCE_PLIST_TO_MERGE)
  250. _juce_append_target_property(file_content BUNDLE_ID ${target} JUCE_BUNDLE_ID)
  251. _juce_append_target_property(file_content XCODE_EXTRA_PLIST_ENTRIES ${target} JUCE_XCODE_EXTRA_PLIST_ENTRIES)
  252. _juce_append_target_property(file_content MICROPHONE_PERMISSION_ENABLED ${target} JUCE_MICROPHONE_PERMISSION_ENABLED)
  253. _juce_append_target_property(file_content MICROPHONE_PERMISSION_TEXT ${target} JUCE_MICROPHONE_PERMISSION_TEXT)
  254. _juce_append_target_property(file_content CAMERA_PERMISSION_ENABLED ${target} JUCE_CAMERA_PERMISSION_ENABLED)
  255. _juce_append_target_property(file_content CAMERA_PERMISSION_TEXT ${target} JUCE_CAMERA_PERMISSION_TEXT)
  256. _juce_append_target_property(file_content BLUETOOTH_PERMISSION_ENABLED ${target} JUCE_BLUETOOTH_PERMISSION_ENABLED)
  257. _juce_append_target_property(file_content BLUETOOTH_PERMISSION_TEXT ${target} JUCE_BLUETOOTH_PERMISSION_TEXT)
  258. _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_ENABLED ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_ENABLED)
  259. _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_TEXT ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_TEXT)
  260. _juce_append_target_property(file_content SHOULD_ADD_STORYBOARD ${target} JUCE_SHOULD_ADD_STORYBOARD)
  261. _juce_append_target_property(file_content LAUNCH_STORYBOARD_FILE ${target} JUCE_LAUNCH_STORYBOARD_FILE)
  262. _juce_append_target_property(file_content ICON_FILE ${target} JUCE_ICON_FILE)
  263. _juce_append_target_property(file_content PROJECT_NAME ${target} JUCE_PRODUCT_NAME)
  264. _juce_append_target_property(file_content COMPANY_COPYRIGHT ${target} JUCE_COMPANY_COPYRIGHT)
  265. _juce_append_target_property(file_content COMPANY_NAME ${target} JUCE_COMPANY_NAME)
  266. _juce_append_target_property(file_content DOCUMENT_EXTENSIONS ${target} JUCE_DOCUMENT_EXTENSIONS)
  267. _juce_append_target_property(file_content FILE_SHARING_ENABLED ${target} JUCE_FILE_SHARING_ENABLED)
  268. _juce_append_target_property(file_content DOCUMENT_BROWSER_ENABLED ${target} JUCE_DOCUMENT_BROWSER_ENABLED)
  269. _juce_append_target_property(file_content STATUS_BAR_HIDDEN ${target} JUCE_STATUS_BAR_HIDDEN)
  270. _juce_append_target_property(file_content REQUIRES_FULL_SCREEN ${target} JUCE_REQUIRES_FULL_SCREEN)
  271. _juce_append_target_property(file_content BACKGROUND_AUDIO_ENABLED ${target} JUCE_BACKGROUND_AUDIO_ENABLED)
  272. _juce_append_target_property(file_content BACKGROUND_BLE_ENABLED ${target} JUCE_BACKGROUND_BLE_ENABLED)
  273. _juce_append_target_property(file_content PUSH_NOTIFICATIONS_ENABLED ${target} JUCE_PUSH_NOTIFICATIONS_ENABLED)
  274. _juce_append_target_property(file_content NETWORK_MULTICAST_ENABLED ${target} JUCE_NETWORK_MULTICAST_ENABLED)
  275. _juce_append_target_property(file_content PLUGIN_MANUFACTURER_CODE ${target} JUCE_PLUGIN_MANUFACTURER_CODE)
  276. _juce_append_target_property(file_content PLUGIN_CODE ${target} JUCE_PLUGIN_CODE)
  277. _juce_append_target_property(file_content IPHONE_SCREEN_ORIENTATIONS ${target} JUCE_IPHONE_SCREEN_ORIENTATIONS)
  278. _juce_append_target_property(file_content IPAD_SCREEN_ORIENTATIONS ${target} JUCE_IPAD_SCREEN_ORIENTATIONS)
  279. _juce_append_target_property(file_content PLUGIN_NAME ${target} JUCE_PLUGIN_NAME)
  280. _juce_append_target_property(file_content PLUGIN_MANUFACTURER ${target} JUCE_COMPANY_NAME)
  281. _juce_append_target_property(file_content PLUGIN_DESCRIPTION ${target} JUCE_DESCRIPTION)
  282. _juce_append_target_property(file_content PLUGIN_AU_EXPORT_PREFIX ${target} JUCE_AU_EXPORT_PREFIX)
  283. _juce_append_target_property(file_content PLUGIN_AU_MAIN_TYPE ${target} JUCE_AU_MAIN_TYPE_CODE)
  284. _juce_append_target_property(file_content IS_AU_SANDBOX_SAFE ${target} JUCE_AU_SANDBOX_SAFE)
  285. _juce_append_target_property(file_content IS_PLUGIN_SYNTH ${target} JUCE_IS_SYNTH)
  286. _juce_append_target_property(file_content IS_PLUGIN_ARA_EFFECT ${target} JUCE_IS_ARA_EFFECT)
  287. _juce_append_target_property(file_content SUPPRESS_AU_PLIST_RESOURCE_USAGE ${target} JUCE_SUPPRESS_AU_PLIST_RESOURCE_USAGE)
  288. _juce_append_target_property(file_content HARDENED_RUNTIME_ENABLED ${target} JUCE_HARDENED_RUNTIME_ENABLED)
  289. _juce_append_target_property(file_content APP_SANDBOX_ENABLED ${target} JUCE_APP_SANDBOX_ENABLED)
  290. _juce_append_target_property(file_content APP_SANDBOX_INHERIT ${target} JUCE_APP_SANDBOX_INHERIT)
  291. _juce_append_target_property(file_content HARDENED_RUNTIME_OPTIONS ${target} JUCE_HARDENED_RUNTIME_OPTIONS)
  292. _juce_append_target_property(file_content APP_SANDBOX_OPTIONS ${target} JUCE_APP_SANDBOX_OPTIONS)
  293. _juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RO)
  294. _juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RW)
  295. _juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RO)
  296. _juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RW)
  297. _juce_append_target_property(file_content APP_SANDBOX_EXCEPTION_IOKIT ${target} JUCE_APP_SANDBOX_EXCEPTION_IOKIT)
  298. _juce_append_target_property(file_content APP_GROUPS_ENABLED ${target} JUCE_APP_GROUPS_ENABLED)
  299. _juce_append_target_property(file_content APP_GROUP_IDS ${target} JUCE_APP_GROUP_IDS)
  300. _juce_append_target_property(file_content IS_PLUGIN ${target} JUCE_IS_PLUGIN)
  301. _juce_append_target_property(file_content ICLOUD_PERMISSIONS_ENABLED ${target} JUCE_ICLOUD_PERMISSIONS_ENABLED)
  302. _juce_append_target_property(file_content IS_AU_PLUGIN_HOST ${target} JUCE_PLUGINHOST_AU)
  303. if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  304. _juce_append_record(file_content IS_IOS 1)
  305. else()
  306. _juce_append_record(file_content IS_IOS 0)
  307. endif()
  308. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  309. set(info_file "${juce_library_code}/Info.txt")
  310. file(WRITE "${info_file}" "${file_content}")
  311. set_target_properties(${target} PROPERTIES JUCE_INFO_FILE "${info_file}")
  312. endfunction()
  313. # In this file, we put things that CMake is only able to divine at generate time, like preprocessor definitions.
  314. # We use the target preprocessor definitions to work out which JUCE modules should go in the JuceHeader.h.
  315. function(_juce_write_generate_time_info target)
  316. _juce_get_module_definitions(${target} OFF module_defs)
  317. _juce_append_record(defs MODULE_DEFINITIONS ${module_defs})
  318. _juce_append_target_property(defs EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME)
  319. _juce_append_target_property(defs PROJECT_NAME ${target} JUCE_PRODUCT_NAME)
  320. _juce_append_target_property(defs VERSION ${target} JUCE_VERSION)
  321. _juce_append_target_property(defs COMPANY_NAME ${target} JUCE_COMPANY_NAME)
  322. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  323. set(defs_file "${juce_library_code}/$<CONFIG>/Defs.txt")
  324. file(GENERATE OUTPUT "${defs_file}" CONTENT "${defs}")
  325. set_target_properties(${target} PROPERTIES JUCE_DEFS_FILE "${defs_file}")
  326. endfunction()
  327. # ==================================================================================================
  328. function(juce_add_binary_data target)
  329. set(one_value_args NAMESPACE HEADER_NAME)
  330. set(multi_value_args SOURCES)
  331. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
  332. list(LENGTH JUCE_ARG_SOURCES num_binary_files)
  333. if(${num_binary_files} LESS 1)
  334. message(FATAL_ERROR "juce_add_binary_data must be passed at least one file to encode")
  335. endif()
  336. add_library(${target} STATIC)
  337. set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
  338. set(juce_binary_data_folder "${CMAKE_CURRENT_BINARY_DIR}/juce_binarydata_${target}/JuceLibraryCode")
  339. set(binary_file_names)
  340. foreach(index RANGE 1 ${num_binary_files})
  341. list(APPEND binary_file_names "${juce_binary_data_folder}/BinaryData${index}.cpp")
  342. endforeach()
  343. file(MAKE_DIRECTORY ${juce_binary_data_folder})
  344. if(NOT JUCE_ARG_NAMESPACE)
  345. set(JUCE_ARG_NAMESPACE BinaryData)
  346. endif()
  347. if(NOT JUCE_ARG_HEADER_NAME)
  348. set(JUCE_ARG_HEADER_NAME BinaryData.h)
  349. endif()
  350. list(APPEND binary_file_names "${juce_binary_data_folder}/${JUCE_ARG_HEADER_NAME}")
  351. set(newline_delimited_input)
  352. foreach(name IN LISTS JUCE_ARG_SOURCES)
  353. _juce_make_absolute(name)
  354. set(newline_delimited_input "${newline_delimited_input}${name}\n")
  355. endforeach()
  356. set(input_file_list "${juce_binary_data_folder}/input_file_list")
  357. file(WRITE "${input_file_list}" "${newline_delimited_input}")
  358. add_custom_command(OUTPUT ${binary_file_names}
  359. COMMAND juce::juceaide binarydata "${JUCE_ARG_NAMESPACE}" "${JUCE_ARG_HEADER_NAME}"
  360. ${juce_binary_data_folder} "${input_file_list}"
  361. WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  362. DEPENDS "${input_file_list}" ${JUCE_ARG_SOURCES}
  363. VERBATIM)
  364. target_sources(${target} PRIVATE "${binary_file_names}")
  365. target_include_directories(${target} INTERFACE ${juce_binary_data_folder})
  366. target_compile_features(${target} PRIVATE cxx_std_17)
  367. # This fixes an issue where Xcode is unable to find binary data during archive.
  368. if(CMAKE_GENERATOR STREQUAL "Xcode")
  369. set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "./")
  370. endif()
  371. if(JUCE_ARG_HEADER_NAME STREQUAL "BinaryData.h")
  372. target_compile_definitions(${target} INTERFACE JUCE_TARGET_HAS_BINARY_DATA=1)
  373. endif()
  374. endfunction()
  375. # ==================================================================================================
  376. function(_juce_version_code version_in out_var)
  377. string(REGEX REPLACE "\\." ";" version_list ${version_in})
  378. list(LENGTH version_list num_version_components)
  379. set(version_major 0)
  380. set(version_minor 0)
  381. set(version_patch 0)
  382. if(num_version_components GREATER 0)
  383. list(GET version_list 0 version_major)
  384. endif()
  385. if(num_version_components GREATER 1)
  386. list(GET version_list 1 version_minor)
  387. endif()
  388. if(num_version_components GREATER 2)
  389. list(GET version_list 2 version_patch)
  390. endif()
  391. math(EXPR hex "(${version_major} << 16) + (${version_minor} << 8) + ${version_patch}"
  392. OUTPUT_FORMAT HEXADECIMAL)
  393. set(${out_var} "${hex}" PARENT_SCOPE)
  394. endfunction()
  395. function(_juce_to_char_literal str out_var help_text)
  396. string(LENGTH "${str}" string_length)
  397. if(NOT "${string_length}" EQUAL "4")
  398. message(WARNING "The ${help_text} code must contain exactly four characters, but it was set to '${str}'")
  399. endif()
  400. # Round-tripping through a file is the simplest way to convert a string to hex...
  401. string(SUBSTRING "${str}" 0 4 four_chars)
  402. string(RANDOM LENGTH 16 random_string)
  403. set(scratch_file "${CMAKE_CURRENT_BINARY_DIR}/${random_string}_ascii_conversion.txt")
  404. file(WRITE "${scratch_file}" "${four_chars}")
  405. file(READ "${scratch_file}" four_chars_hex HEX)
  406. file(REMOVE "${scratch_file}")
  407. string(SUBSTRING "${four_chars_hex}00000000" 0 8 four_chars_hex)
  408. set(${out_var} "${four_chars_hex}" PARENT_SCOPE)
  409. endfunction()
  410. # ==================================================================================================
  411. function(juce_generate_juce_header target)
  412. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  413. if(NOT juce_library_code)
  414. message(FATAL_ERROR "Target ${target} does not have a generated sources directory. Ensure it was created with a juce_add_* function")
  415. endif()
  416. set(juce_header ${juce_library_code}/JuceHeader.h)
  417. target_sources(${target} PRIVATE ${juce_header})
  418. set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${target},JUCE_DEFS_FILE>>)
  419. set(extra_args)
  420. add_custom_command(OUTPUT "${juce_header}"
  421. COMMAND juce::juceaide header "${defs_file}" "${juce_header}" ${extra_args}
  422. DEPENDS "${defs_file}"
  423. VERBATIM)
  424. endfunction()
  425. # ==================================================================================================
  426. function(_juce_execute_juceaide)
  427. if(NOT TARGET juce::juceaide)
  428. message(FATAL_ERROR "The juceaide target does not exist")
  429. endif()
  430. get_target_property(juceaide_location juce::juceaide IMPORTED_LOCATION)
  431. if(NOT EXISTS "${juceaide_location}")
  432. message(FATAL_ERROR "juceaide was imported, but it doesn't exist!")
  433. endif()
  434. execute_process(COMMAND "${juceaide_location}" ${ARGN}
  435. RESULT_VARIABLE result_variable
  436. OUTPUT_VARIABLE output
  437. ERROR_VARIABLE output)
  438. if(result_variable)
  439. message(FATAL_ERROR "Running juceaide failed:\ncommand: ${juceaide_location} ${ARGN}\noutput: ${output}")
  440. endif()
  441. endfunction()
  442. function(_juce_set_output_name target name)
  443. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
  444. set_target_properties(${target} PROPERTIES
  445. OUTPUT_NAME ${name}
  446. XCODE_ATTRIBUTE_PRODUCT_NAME ${name})
  447. endif()
  448. endfunction()
  449. function(_juce_check_icon_files_exist icon_files)
  450. foreach(file IN LISTS icon_files)
  451. if(NOT EXISTS "${file}")
  452. message(FATAL_ERROR "Could not find icon file: ${file}")
  453. endif()
  454. endforeach()
  455. endfunction()
  456. function(_juce_generate_icon source_target dest_target)
  457. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  458. get_target_property(juce_property_icon_big ${source_target} JUCE_ICON_BIG)
  459. get_target_property(juce_property_icon_small ${source_target} JUCE_ICON_SMALL)
  460. set(icon_args)
  461. if(juce_property_icon_big)
  462. list(APPEND icon_args "${juce_property_icon_big}")
  463. endif()
  464. if(juce_property_icon_small)
  465. list(APPEND icon_args "${juce_property_icon_small}")
  466. endif()
  467. set(generated_icon)
  468. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  469. if(NOT icon_args)
  470. return()
  471. endif()
  472. _juce_check_icon_files_exist("${icon_args}")
  473. set(generated_icon "${juce_library_code}/Icon.icns")
  474. # To get compiled properly, we need the icon before the plist is generated!
  475. _juce_execute_juceaide(macicon "${generated_icon}" ${icon_args})
  476. set_source_files_properties(${generated_icon} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
  477. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  478. if(NOT icon_args)
  479. return()
  480. endif()
  481. _juce_check_icon_files_exist("${icon_args}")
  482. set(generated_icon "${juce_library_code}/icon.ico")
  483. _juce_execute_juceaide(winicon "${generated_icon}" ${icon_args})
  484. elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  485. get_target_property(generated_icon ${source_target} JUCE_CUSTOM_XCASSETS_FOLDER)
  486. if(icon_args AND (NOT generated_icon))
  487. _juce_check_icon_files_exist("${icon_args}")
  488. set(out_path "${juce_library_code}/${dest_target}")
  489. set(generated_icon "${out_path}/Images.xcassets")
  490. # To get compiled properly, we need iOS assets at configure time!
  491. _juce_execute_juceaide(iosassets "${out_path}" ${icon_args})
  492. endif()
  493. if(NOT generated_icon)
  494. return()
  495. endif()
  496. set_target_properties(${dest_target} PROPERTIES
  497. XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon")
  498. get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD)
  499. if(NOT add_storyboard)
  500. set_target_properties(${dest_target} PROPERTIES
  501. XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME "LaunchImage")
  502. endif()
  503. endif()
  504. if(generated_icon)
  505. _juce_check_icon_files_exist("${generated_icon}")
  506. target_sources(${dest_target} PRIVATE ${generated_icon})
  507. set_target_properties(${source_target} ${dest_target} PROPERTIES
  508. JUCE_ICON_FILE "${generated_icon}"
  509. RESOURCE "${generated_icon}")
  510. endif()
  511. endfunction()
  512. function(_juce_add_xcode_entitlements source_target dest_target)
  513. get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING)
  514. get_target_property(input_info_file ${source_target} JUCE_INFO_FILE)
  515. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  516. set(entitlements_file "${juce_library_code}/${dest_target}.entitlements")
  517. _juce_execute_juceaide(entitlements "${juce_kind_string}" "${input_info_file}" "${entitlements_file}")
  518. set_target_properties(${dest_target} PROPERTIES
  519. XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${entitlements_file}")
  520. endfunction()
  521. function(_juce_configure_bundle source_target dest_target)
  522. _juce_generate_icon(${source_target} ${dest_target})
  523. _juce_write_configure_time_info(${source_target})
  524. if(NOT APPLE)
  525. return()
  526. endif()
  527. get_target_property(generated_icon ${source_target} JUCE_ICON_FILE)
  528. set(icon_dependency)
  529. if(generated_icon)
  530. set(icon_dependency "${generated_icon}")
  531. endif()
  532. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  533. get_target_property(input_info_file ${source_target} JUCE_INFO_FILE)
  534. set(this_output_info_dir "${juce_library_code}/${dest_target}")
  535. set(this_output_pkginfo "${this_output_info_dir}/PkgInfo")
  536. set(this_output_plist "${this_output_info_dir}/Info.plist")
  537. get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING)
  538. _juce_execute_juceaide(plist "${juce_kind_string}" "${input_info_file}" "${this_output_plist}")
  539. set_target_properties(${dest_target} PROPERTIES
  540. BUNDLE TRUE
  541. MACOSX_BUNDLE_INFO_PLIST "${this_output_plist}")
  542. add_custom_command(OUTPUT "${this_output_pkginfo}"
  543. COMMAND juce::juceaide pkginfo "${juce_kind_string}" "${this_output_pkginfo}"
  544. VERBATIM)
  545. set(output_folder "$<TARGET_BUNDLE_CONTENT_DIR:${dest_target}>")
  546. target_sources(${dest_target} PRIVATE "${this_output_pkginfo}")
  547. set_source_files_properties("${this_output_pkginfo}" PROPERTIES
  548. HEADER_FILE_ONLY TRUE
  549. GENERATED TRUE)
  550. add_custom_command(TARGET ${dest_target} POST_BUILD
  551. COMMAND "${CMAKE_COMMAND}" -E copy "${this_output_pkginfo}" "${output_folder}"
  552. DEPENDS "${this_output_pkginfo}"
  553. VERBATIM)
  554. _juce_add_xcode_entitlements(${source_target} ${dest_target})
  555. if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  556. get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD)
  557. if(add_storyboard)
  558. get_target_property(storyboard_file ${source_target} JUCE_LAUNCH_STORYBOARD_FILE)
  559. if(NOT EXISTS "${storyboard_file}")
  560. message(FATAL_ERROR "Could not find storyboard file: ${storyboard_file}")
  561. endif()
  562. target_sources(${dest_target} PRIVATE "${storyboard_file}")
  563. set_property(TARGET ${dest_target} APPEND PROPERTY RESOURCE "${storyboard_file}")
  564. endif()
  565. endif()
  566. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  567. set_target_properties(${dest_target} PROPERTIES
  568. XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--timestamp")
  569. endif()
  570. set_target_properties(${dest_target} PROPERTIES
  571. XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME
  572. "$<TARGET_PROPERTY:${source_target},JUCE_HARDENED_RUNTIME_ENABLED>"
  573. XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY
  574. "$<TARGET_PROPERTY:${source_target},JUCE_TARGETED_DEVICE_FAMILY>")
  575. if(juce_kind_string STREQUAL "AUv3 AppExtension")
  576. get_target_property(source_bundle_id ${source_target} JUCE_BUNDLE_ID)
  577. if(source_bundle_id MATCHES "\\.([^.]+)$")
  578. set_target_properties(${dest_target} PROPERTIES
  579. XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
  580. "${source_bundle_id}.${CMAKE_MATCH_1}AUv3")
  581. else()
  582. message(FATAL_ERROR "Bundle ID should contain at least one `.`!")
  583. endif()
  584. else()
  585. set_target_properties(${dest_target} PROPERTIES
  586. XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
  587. $<TARGET_PROPERTY:${source_target},JUCE_BUNDLE_ID>)
  588. endif()
  589. if(CMAKE_GENERATOR STREQUAL "Xcode")
  590. get_target_property(product_name ${source_target} JUCE_PRODUCT_NAME)
  591. set(skip_install NO)
  592. set(install_path "$(LOCAL_APPS_DIR)")
  593. if(juce_kind_string STREQUAL "AUv3 AppExtension")
  594. set(skip_install YES)
  595. set(install_path "")
  596. endif()
  597. set_target_properties(${dest_target} PROPERTIES
  598. XCODE_ATTRIBUTE_INSTALL_PATH "${install_path}"
  599. XCODE_ATTRIBUTE_SKIP_INSTALL "${skip_install}")
  600. endif()
  601. endfunction()
  602. function(_juce_add_resources_rc source_target dest_target)
  603. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
  604. return()
  605. endif()
  606. if(NOT TARGET ${source_target}_rc_lib)
  607. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  608. get_target_property(input_info_file ${source_target} JUCE_INFO_FILE)
  609. get_target_property(generated_icon ${source_target} JUCE_ICON_FILE)
  610. set(dependency)
  611. if(generated_icon)
  612. set(dependency DEPENDS "${generated_icon}")
  613. endif()
  614. set(resource_rc_file "${juce_library_code}/${source_target}_resources.rc")
  615. add_custom_command(OUTPUT "${resource_rc_file}"
  616. COMMAND juce::juceaide rcfile "${input_info_file}" "${resource_rc_file}"
  617. ${dependency}
  618. VERBATIM)
  619. add_library(${source_target}_rc_lib OBJECT ${resource_rc_file})
  620. set(compile_defs $<TARGET_GENEX_EVAL:${source_target},$<TARGET_PROPERTY:${source_target},COMPILE_DEFINITIONS>>)
  621. set(include_dirs $<TARGET_GENEX_EVAL:${source_target},$<TARGET_PROPERTY:${source_target},INCLUDE_DIRECTORIES>>)
  622. set(filtered $<FILTER:${compile_defs},INCLUDE,JUCE_USER_DEFINED_RC_FILE=>)
  623. set(has_custom_rc_include $<BOOL:${filtered}>)
  624. target_include_directories(${source_target}_rc_lib
  625. PRIVATE $<${has_custom_rc_include}:${include_dirs}>)
  626. set_source_files_properties(${resource_rc_file} PROPERTIES
  627. COMPILE_DEFINITIONS $<${has_custom_rc_include}:${compile_defs}>)
  628. endif()
  629. target_link_libraries(${dest_target} PRIVATE ${source_target}_rc_lib)
  630. endfunction()
  631. function(_juce_configure_app_bundle source_target dest_target)
  632. set_target_properties(${dest_target} PROPERTIES
  633. JUCE_TARGET_KIND_STRING "App"
  634. MACOSX_BUNDLE TRUE
  635. WIN32_EXECUTABLE TRUE)
  636. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  637. set(nib_path "${JUCE_CMAKE_UTILS_DIR}/RecentFilesMenuTemplate.nib")
  638. target_sources("${dest_target}" PRIVATE "${nib_path}")
  639. set_source_files_properties("${nib_path}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
  640. endif()
  641. endfunction()
  642. # ==================================================================================================
  643. function(_juce_create_windows_package source_target dest_target extension default_icon x32folder x64folder)
  644. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
  645. return()
  646. endif()
  647. get_target_property(products_folder ${dest_target} LIBRARY_OUTPUT_DIRECTORY)
  648. set(product_name $<TARGET_PROPERTY:${source_target},JUCE_PRODUCT_NAME>)
  649. set(output_folder "${products_folder}/${product_name}.${extension}")
  650. set(is_x64 $<EQUAL:${CMAKE_SIZEOF_VOID_P},8>)
  651. set(arch_string $<IF:${is_x64},${x64folder},${x32folder}>)
  652. set_target_properties(${dest_target}
  653. PROPERTIES
  654. PDB_OUTPUT_DIRECTORY "${products_folder}"
  655. LIBRARY_OUTPUT_DIRECTORY "${output_folder}/Contents/${arch_string}")
  656. get_target_property(icon_file ${source_target} JUCE_ICON_FILE)
  657. if(NOT icon_file)
  658. set(icon_file "${default_icon}")
  659. endif()
  660. if(icon_file)
  661. set(desktop_ini "${output_folder}/desktop.ini")
  662. set(plugin_ico "${output_folder}/Plugin.ico")
  663. file(GENERATE OUTPUT "${desktop_ini}"
  664. CONTENT
  665. "[.ShellClassInfo]\nIconResource=Plugin.ico,0\nIconFile=Plugin.ico\nIconIndex=0\n")
  666. add_custom_command(TARGET ${dest_target} POST_BUILD
  667. COMMAND "${CMAKE_COMMAND}" -E copy "${icon_file}" "${plugin_ico}"
  668. COMMAND attrib +s "${desktop_ini}"
  669. COMMAND attrib +s "${output_folder}"
  670. DEPENDS "${icon_file}" "${desktop_ini}"
  671. VERBATIM)
  672. endif()
  673. endfunction()
  674. # ==================================================================================================
  675. function(_juce_add_unity_plugin_prefix_if_necessary name out_var)
  676. string(TOLOWER "${name}" lower)
  677. if(NOT lower MATCHES "^audioplugin")
  678. set(${out_var} "audioplugin_${name}" PARENT_SCOPE)
  679. else()
  680. set(${out_var} "${name}" PARENT_SCOPE)
  681. endif()
  682. endfunction()
  683. function(_juce_add_unity_script_file shared_target out_var)
  684. set(script_in "${JUCE_CMAKE_UTILS_DIR}/UnityPluginGUIScript.cs.in")
  685. get_target_property(plugin_name ${shared_target} JUCE_PLUGIN_NAME)
  686. get_target_property(plugin_vendor ${shared_target} JUCE_COMPANY_NAME)
  687. get_target_property(plugin_description ${shared_target} JUCE_DESCRIPTION)
  688. string(REGEX REPLACE " +" "_" plugin_class_name "${plugin_name}")
  689. get_target_property(juce_library_code ${shared_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  690. _juce_add_unity_plugin_prefix_if_necessary("${plugin_name}" script_prefix)
  691. set(script_out "${juce_library_code}/${script_prefix}_UnityScript.cs")
  692. configure_file(${script_in} ${script_out})
  693. set(${out_var} "${script_out}" PARENT_SCOPE)
  694. endfunction()
  695. # ==================================================================================================
  696. function(_juce_copy_dir target from to)
  697. # This is a shim to make CMake copy a whole directory, rather than just
  698. # the contents of a directory
  699. add_custom_command(TARGET ${target} POST_BUILD
  700. COMMAND "${CMAKE_COMMAND}"
  701. "-Dsrc=${from}"
  702. "-Ddest=${to}"
  703. "-P" "${JUCE_CMAKE_UTILS_DIR}/copyDir.cmake"
  704. VERBATIM)
  705. endfunction()
  706. function(_juce_set_copy_properties shared_code target from to_property)
  707. get_target_property(destination "${shared_code}" "${to_property}")
  708. if(destination)
  709. set_target_properties("${target}" PROPERTIES JUCE_PLUGIN_COPY_DIR "${destination}")
  710. endif()
  711. set_target_properties("${target}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "${from}")
  712. endfunction()
  713. function(_juce_adhoc_sign target)
  714. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  715. return()
  716. endif()
  717. get_target_property(bundle "${target}" BUNDLE)
  718. set(src "$<TARGET_FILE:${target}>")
  719. if(bundle)
  720. set(src "$<TARGET_BUNDLE_DIR:${target}>")
  721. endif()
  722. add_custom_command(TARGET ${target} POST_BUILD
  723. COMMAND "${CMAKE_COMMAND}"
  724. "-Dsrc=${src}"
  725. "-P" "${JUCE_CMAKE_UTILS_DIR}/checkBundleSigning.cmake"
  726. VERBATIM)
  727. endfunction()
  728. function(juce_enable_copy_plugin_step shared_code_target)
  729. get_target_property(step_added ${shared_code_target} _JUCE_PLUGIN_COPY_STEP_ADDED)
  730. if(step_added)
  731. message(WARNING "Plugin copy step requested multiple times for ${shared_code_target}")
  732. return()
  733. endif()
  734. set_target_properties(${shared_code_target} PROPERTIES _JUCE_PLUGIN_COPY_STEP_ADDED TRUE)
  735. get_target_property(active_targets "${shared_code_target}" JUCE_ACTIVE_PLUGIN_TARGETS)
  736. foreach(target IN LISTS active_targets)
  737. get_target_property(target_kind "${target}" JUCE_TARGET_KIND_STRING)
  738. if(target_kind STREQUAL "App")
  739. continue()
  740. endif()
  741. _juce_adhoc_sign("${target}")
  742. get_target_property(source "${target}" JUCE_PLUGIN_ARTEFACT_FILE)
  743. if(NOT source)
  744. continue()
  745. endif()
  746. get_target_property(dest "${target}" JUCE_PLUGIN_COPY_DIR)
  747. if(dest)
  748. _juce_copy_dir("${target}" "${source}" "$<GENEX_EVAL:${dest}>")
  749. else()
  750. message(WARNING "Target '${target}' requested copy but no destination is set")
  751. endif()
  752. endforeach()
  753. endfunction()
  754. # ==================================================================================================
  755. function(_juce_add_lv2_manifest_helper_target)
  756. if(TARGET juce_lv2_helper OR (CMAKE_SYSTEM_NAME STREQUAL "iOS") OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
  757. return()
  758. endif()
  759. get_target_property(module_path juce::juce_audio_plugin_client INTERFACE_JUCE_MODULE_PATH)
  760. set(source "${module_path}/juce_audio_plugin_client/LV2/juce_LV2ManifestHelper.cpp")
  761. add_executable(juce_lv2_helper "${source}")
  762. add_executable(juce::juce_lv2_helper ALIAS juce_lv2_helper)
  763. target_compile_features(juce_lv2_helper PRIVATE cxx_std_17)
  764. set_target_properties(juce_lv2_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
  765. set(THREADS_PREFER_PTHREAD_FLAG ON)
  766. find_package(Threads REQUIRED)
  767. target_link_libraries(juce_lv2_helper PRIVATE Threads::Threads ${CMAKE_DL_LIBS})
  768. endfunction()
  769. # ==================================================================================================
  770. function(_juce_add_vst3_manifest_helper_target)
  771. if(TARGET juce_vst3_helper
  772. OR (CMAKE_SYSTEM_NAME STREQUAL "iOS")
  773. OR (CMAKE_SYSTEM_NAME STREQUAL "Android")
  774. OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  775. return()
  776. endif()
  777. get_target_property(module_path juce::juce_audio_processors INTERFACE_JUCE_MODULE_PATH)
  778. set(vst3_dir "${module_path}/juce_audio_processors/format_types/VST3_SDK")
  779. set(extension "cpp")
  780. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  781. set(extension "mm")
  782. endif()
  783. set(source "${module_path}/juce_audio_plugin_client/VST3/juce_VST3ManifestHelper.${extension}")
  784. add_executable(juce_vst3_helper "${source}")
  785. add_executable(juce::juce_vst3_helper ALIAS juce_vst3_helper)
  786. target_include_directories(juce_vst3_helper PRIVATE "${vst3_dir}" "${module_path}")
  787. add_library(juce_interface_definitions INTERFACE)
  788. _juce_add_standard_defs(juce_interface_definitions)
  789. target_link_libraries(juce_vst3_helper PRIVATE juce_interface_definitions)
  790. target_compile_features(juce_vst3_helper PRIVATE cxx_std_17)
  791. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  792. _juce_link_frameworks(juce_vst3_helper PRIVATE Cocoa)
  793. target_compile_options(juce_vst3_helper PRIVATE -fobjc-arc)
  794. endif()
  795. if(MSYS OR MINGW)
  796. target_link_options(juce_vst3_helper PRIVATE -municode)
  797. endif()
  798. set_target_properties(juce_vst3_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
  799. set(THREADS_PREFER_PTHREAD_FLAG ON)
  800. find_package(Threads REQUIRED)
  801. target_link_libraries(juce_vst3_helper PRIVATE Threads::Threads ${CMAKE_DL_LIBS} juce_recommended_config_flags)
  802. if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
  803. target_link_libraries(juce_vst3_helper PRIVATE stdc++fs)
  804. endif()
  805. endfunction()
  806. function(juce_enable_vst3_manifest_step shared_code_target)
  807. get_target_property(manifest_step_added ${shared_code_target} _JUCE_VST3_MANIFEST_STEP_ADDED)
  808. if(manifest_step_added)
  809. message(WARNING "VST3 manifest generation has already been enabled for target ${shared_code_target}. "
  810. "You may need to set VST3_AUTO_MANIFEST FALSE in juce_add_plugin, and/or check that you're "
  811. "not calling juce_enable_vst3_manifest_step multiple times.")
  812. return()
  813. endif()
  814. get_target_property(copy_step_added ${shared_code_target} _JUCE_PLUGIN_COPY_STEP_ADDED)
  815. if(copy_step_added)
  816. message(FATAL_ERROR "VST3 manifest generation would run after plugin copy step, so it has been disabled. "
  817. "If you're manually calling juce_enable_vst3_manifest_step, then you probably need to call "
  818. "juce_enable_copy_plugin_step too.")
  819. endif()
  820. if((MSYS OR MINGW) AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
  821. message(WARNING "VST3 manifest generation is disabled for ${shared_code_target} because the compiler is not supported.")
  822. return()
  823. endif()
  824. set(target_name ${shared_code_target}_VST3)
  825. get_target_property(product ${target_name} JUCE_PLUGIN_ARTEFACT_FILE)
  826. if(NOT product)
  827. message(FATAL_ERROR "Property JUCE_PLUGIN_ARTEFACT_FILE not set for ${target_name}")
  828. endif()
  829. # Add a target for the helper tool
  830. _juce_add_vst3_manifest_helper_target()
  831. get_target_property(target_version_string ${shared_code_target} JUCE_VERSION)
  832. # Use the helper tool to write out the moduleinfo.json
  833. add_custom_command(TARGET ${target_name} POST_BUILD
  834. COMMAND ${CMAKE_COMMAND} -E make_directory "${product}/Contents/Resources"
  835. COMMAND juce_vst3_helper
  836. -create
  837. -version "${target_version_string}"
  838. -path "${product}"
  839. -output "${product}/Contents/Resources/moduleinfo.json"
  840. VERBATIM)
  841. set_target_properties(${shared_code_target} PROPERTIES _JUCE_VST3_MANIFEST_STEP_ADDED TRUE)
  842. endfunction()
  843. # ==================================================================================================
  844. function(_juce_set_plugin_target_properties shared_code_target kind)
  845. set(target_name ${shared_code_target}_${kind})
  846. set_target_properties(${target_name} PROPERTIES
  847. ARCHIVE_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},ARCHIVE_OUTPUT_DIRECTORY>>/${kind}"
  848. LIBRARY_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},LIBRARY_OUTPUT_DIRECTORY>>/${kind}"
  849. RUNTIME_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},RUNTIME_OUTPUT_DIRECTORY>>/${kind}")
  850. get_target_property(products_folder ${target_name} LIBRARY_OUTPUT_DIRECTORY)
  851. set(product_name $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
  852. if(kind STREQUAL "Standalone")
  853. get_target_property(is_bundle "${target_name}" BUNDLE)
  854. if(is_bundle)
  855. set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_BUNDLE_DIR:${target_name}>")
  856. else()
  857. set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_FILE:${target_name}>")
  858. endif()
  859. elseif(kind STREQUAL "VST3")
  860. set_target_properties(${target_name} PROPERTIES
  861. BUNDLE_EXTENSION vst3
  862. PREFIX ""
  863. SUFFIX .vst3
  864. BUNDLE TRUE
  865. XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst3
  866. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  867. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  868. _juce_create_windows_package(${shared_code_target} ${target_name} vst3 "" x86-win x86_64-win)
  869. set(output_path "${products_folder}/${product_name}.vst3")
  870. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  871. set_target_properties(${target_name} PROPERTIES
  872. SUFFIX .so
  873. LIBRARY_OUTPUT_DIRECTORY "${output_path}/Contents/${JUCE_TARGET_ARCHITECTURE}-linux")
  874. endif()
  875. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_VST3_COPY_DIR)
  876. _juce_adhoc_sign(${target_name})
  877. get_target_property(vst3_auto_manifest ${shared_code_target} JUCE_VST3_AUTO_MANIFEST)
  878. add_custom_command(TARGET ${target_name} POST_BUILD
  879. COMMAND ${CMAKE_COMMAND} -E echo "removing moduleinfo.json"
  880. COMMAND ${CMAKE_COMMAND} -E remove -f
  881. "${output_path}/Contents/moduleinfo.json"
  882. "${output_path}/Contents/Resources/moduleinfo.json")
  883. if(vst3_auto_manifest)
  884. juce_enable_vst3_manifest_step(${shared_code_target})
  885. endif()
  886. elseif(kind STREQUAL "VST")
  887. set_target_properties(${target_name} PROPERTIES
  888. BUNDLE_EXTENSION vst
  889. BUNDLE TRUE
  890. XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst
  891. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  892. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  893. set(output_path "$<TARGET_FILE:${target_name}>")
  894. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  895. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  896. endif()
  897. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_VST_COPY_DIR)
  898. elseif(kind STREQUAL "AU")
  899. set_target_properties(${target_name} PROPERTIES
  900. BUNDLE_EXTENSION component
  901. XCODE_ATTRIBUTE_WRAPPER_EXTENSION component
  902. BUNDLE TRUE
  903. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  904. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  905. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  906. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_AU_COPY_DIR)
  907. elseif(kind STREQUAL "AUv3")
  908. set_target_properties(${target_name} PROPERTIES
  909. XCODE_PRODUCT_TYPE "com.apple.product-type.app-extension"
  910. BUNDLE_EXTENSION appex
  911. XCODE_ATTRIBUTE_WRAPPER_EXTENSION appex
  912. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  913. elseif(kind STREQUAL "AAX")
  914. set_target_properties(${target_name} PROPERTIES
  915. BUNDLE_EXTENSION aaxplugin
  916. PREFIX ""
  917. SUFFIX .aaxplugin
  918. XCODE_ATTRIBUTE_WRAPPER_EXTENSION aaxplugin
  919. BUNDLE TRUE
  920. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  921. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  922. get_target_property(default_icon juce_aax_sdk INTERFACE_JUCE_AAX_DEFAULT_ICON)
  923. _juce_create_windows_package(${shared_code_target} ${target_name} aaxplugin "${default_icon}" Win32 x64)
  924. set(output_path "${products_folder}/${product_name}.aaxplugin")
  925. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_AAX_COPY_DIR)
  926. elseif(kind STREQUAL "Unity")
  927. set_target_properties(${target_name} PROPERTIES
  928. BUNDLE_EXTENSION bundle
  929. XCODE_ATTRIBUTE_WRAPPER_EXTENSION bundle
  930. BUNDLE TRUE
  931. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  932. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  933. _juce_add_unity_script_file(${shared_code_target} script_file)
  934. target_sources(${target_name} PRIVATE "${script_file}")
  935. set_source_files_properties("${script_file}" PROPERTIES
  936. GENERATED TRUE
  937. MACOSX_PACKAGE_LOCATION Resources)
  938. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  939. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  940. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_UNITY_COPY_DIR)
  941. else()
  942. # On windows and linux, the gui script needs to be copied next to the unity output
  943. add_custom_command(TARGET ${target_name} POST_BUILD
  944. COMMAND "${CMAKE_COMMAND}" -E copy "${script_file}" "${products_folder}"
  945. DEPENDS "${script_file}"
  946. VERBATIM)
  947. _juce_set_copy_properties(${shared_code_target}
  948. ${target_name}
  949. "$<TARGET_FILE:${target_name}>"
  950. JUCE_UNITY_COPY_DIR)
  951. _juce_set_copy_properties(${shared_code_target}
  952. ${target_name}
  953. "${script_file}"
  954. JUCE_UNITY_COPY_DIR)
  955. endif()
  956. elseif(kind STREQUAL "LV2")
  957. set_target_properties(${target_name} PROPERTIES BUNDLE FALSE)
  958. get_target_property(JUCE_LV2URI "${shared_code_target}" JUCE_LV2URI)
  959. if(NOT JUCE_LV2URI MATCHES "https?://.*|urn:.*")
  960. message(WARNING
  961. "LV2URI should be well-formed with an 'http' or 'urn' prefix. "
  962. "Check the LV2URI argument to juce_add_plugin.")
  963. endif()
  964. set(source_header "${JUCE_CMAKE_UTILS_DIR}/JuceLV2Defines.h.in")
  965. get_target_property(juce_library_code "${shared_code_target}" JUCE_GENERATED_SOURCES_DIRECTORY)
  966. configure_file("${source_header}" "${juce_library_code}/JuceLV2Defines.h")
  967. set(output_path "${products_folder}/${product_name}.lv2")
  968. set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_path}")
  969. _juce_adhoc_sign(${target_name})
  970. _juce_add_lv2_manifest_helper_target()
  971. add_custom_command(TARGET ${target_name} POST_BUILD
  972. COMMAND juce_lv2_helper "$<TARGET_FILE:${target_name}>"
  973. VERBATIM)
  974. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_LV2_COPY_DIR)
  975. endif()
  976. endfunction()
  977. # Place plugin wrapper targets alongside the shared code target in IDEs
  978. function(_juce_set_plugin_folder_property shared_target wrapper_target)
  979. get_target_property(folder_to_use "${shared_target}" FOLDER)
  980. if(folder_to_use STREQUAL "folder_to_use-NOTFOUND")
  981. set_target_properties("${shared_target}" PROPERTIES FOLDER "${shared_target}")
  982. elseif(NOT folder_to_use MATCHES ".*${shared_target}$")
  983. set_target_properties("${shared_target}" PROPERTIES FOLDER "${folder_to_use}/${shared_target}")
  984. endif()
  985. get_target_property(folder_to_use "${shared_target}" FOLDER)
  986. set_target_properties("${wrapper_target}" PROPERTIES FOLDER "${folder_to_use}")
  987. endfunction()
  988. # Convert the cmake plugin kind ids to strings understood by ProjectType::Target::typeFromName
  989. function(_juce_get_plugin_kind_name kind out_var)
  990. if(kind STREQUAL "AU")
  991. set(${out_var} "AU" PARENT_SCOPE)
  992. elseif(kind STREQUAL "AUv3")
  993. set(${out_var} "AUv3 AppExtension" PARENT_SCOPE)
  994. elseif(kind STREQUAL "AAX")
  995. set(${out_var} "AAX" PARENT_SCOPE)
  996. elseif(kind STREQUAL "LV2")
  997. set(${out_var} "LV2" PARENT_SCOPE)
  998. elseif(kind STREQUAL "Standalone")
  999. set(${out_var} "Standalone Plugin" PARENT_SCOPE)
  1000. elseif(kind STREQUAL "Unity")
  1001. set(${out_var} "Unity Plugin" PARENT_SCOPE)
  1002. elseif(kind STREQUAL "VST")
  1003. set(${out_var} "VST" PARENT_SCOPE)
  1004. elseif(kind STREQUAL "VST3")
  1005. set(${out_var} "VST3" PARENT_SCOPE)
  1006. endif()
  1007. endfunction()
  1008. function(_juce_link_plugin_wrapper shared_code_target kind)
  1009. set(target_name ${shared_code_target}_${kind})
  1010. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  1011. add_library(${target_name} SHARED)
  1012. elseif((kind STREQUAL "Standalone") OR (kind STREQUAL "AUv3"))
  1013. add_executable(${target_name} WIN32 MACOSX_BUNDLE)
  1014. else()
  1015. add_library(${target_name} MODULE)
  1016. endif()
  1017. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  1018. target_link_options(${target_name} PRIVATE "-Wl,--no-undefined")
  1019. endif()
  1020. # We re-export the shared code's private include dirs, because the wrapper targets need to
  1021. # see the module headers. We don't just link publicly, because that would introduce
  1022. # conflicting macro definitions.
  1023. target_include_directories(${target_name} PRIVATE
  1024. $<TARGET_PROPERTY:${shared_code_target},INCLUDE_DIRECTORIES>)
  1025. target_link_libraries(${target_name} PRIVATE
  1026. ${shared_code_target}
  1027. juce::juce_audio_plugin_client_${kind})
  1028. _juce_set_output_name(${target_name} $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
  1029. _juce_set_plugin_folder_property("${shared_code_target}" "${target_name}")
  1030. _juce_get_plugin_kind_name(${kind} juce_kind_string)
  1031. set_target_properties(${target_name} PROPERTIES
  1032. XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO
  1033. XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES YES
  1034. POSITION_INDEPENDENT_CODE TRUE
  1035. VISIBILITY_INLINES_HIDDEN TRUE
  1036. C_VISIBILITY_PRESET hidden
  1037. CXX_VISIBILITY_PRESET hidden
  1038. JUCE_TARGET_KIND_STRING "${juce_kind_string}")
  1039. # Under the Xcode generator, POST_BUILD commands (including the plugin copy step) run before
  1040. # signing, but M1 macs will only load signed binaries. Setting "adhoc_codesign" forces the
  1041. # linker to sign bundles, so that they can be loaded even if they are copied before the "real"
  1042. # signing step. See issue 21854 on the CMake Gitlab repo.
  1043. if("${CMAKE_GENERATOR};${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Xcode;Darwin;arm64")
  1044. target_link_options(${target_name} PRIVATE LINKER:-adhoc_codesign)
  1045. endif()
  1046. add_dependencies(${shared_code_target}_All ${target_name})
  1047. if(NOT kind STREQUAL "LV2")
  1048. _juce_configure_bundle(${shared_code_target} ${target_name})
  1049. else()
  1050. _juce_write_configure_time_info(${shared_code_target})
  1051. endif()
  1052. _juce_set_plugin_target_properties(${shared_code_target} ${kind})
  1053. _juce_add_resources_rc(${shared_code_target} ${target_name})
  1054. endfunction()
  1055. # ==================================================================================================
  1056. function(_juce_get_vst3_category_string target out_var)
  1057. get_target_property(vst3_categories ${target} JUCE_VST3_CATEGORIES)
  1058. if((NOT Fx IN_LIST vst3_categories) AND (NOT Instrument IN_LIST vst3_categories))
  1059. get_target_property(is_synth ${target} JUCE_IS_SYNTH)
  1060. if(is_synth)
  1061. set(first_type Instrument)
  1062. else()
  1063. set(first_type Fx)
  1064. endif()
  1065. list(INSERT vst3_categories 0 ${first_type})
  1066. else()
  1067. if(Instrument IN_LIST vst3_categories)
  1068. list(REMOVE_ITEM vst3_categories Instrument)
  1069. list(INSERT vst3_categories 0 Instrument)
  1070. endif()
  1071. if(Fx IN_LIST vst3_categories)
  1072. list(REMOVE_ITEM vst3_categories Fx)
  1073. list(INSERT vst3_categories 0 Fx)
  1074. endif()
  1075. endif()
  1076. string(REGEX REPLACE ";" "|" result "${vst3_categories}")
  1077. set(${out_var} ${result} PARENT_SCOPE)
  1078. endfunction()
  1079. function(_juce_configure_plugin_targets target)
  1080. _juce_set_output_name(${target} $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>_SharedCode)
  1081. target_link_libraries(${target} PRIVATE juce::juce_audio_plugin_client)
  1082. get_target_property(enabled_formats ${target} JUCE_FORMATS)
  1083. set(active_formats)
  1084. _juce_get_platform_plugin_kinds(plugin_kinds)
  1085. foreach(kind IN LISTS plugin_kinds)
  1086. if(kind IN_LIST enabled_formats)
  1087. list(APPEND active_formats "${kind}")
  1088. endif()
  1089. endforeach()
  1090. if((VST IN_LIST active_formats) AND (NOT TARGET juce_vst2_sdk))
  1091. message(FATAL_ERROR "Use juce_set_vst2_sdk_path to set up the VST sdk before adding VST targets")
  1092. elseif((AAX IN_LIST active_formats) AND (NOT TARGET juce_aax_sdk))
  1093. message(FATAL_ERROR "Use juce_set_aax_sdk_path to set up the AAX sdk before adding AAX targets")
  1094. endif()
  1095. _juce_add_standard_defs(${target})
  1096. _juce_add_plugin_definitions(${target} PRIVATE ${active_formats})
  1097. # The plugin wrappers need to know what other modules are available, especially
  1098. # juce_audio_utils and juce_gui_basics. We achieve this by searching for
  1099. # JUCE_MODULE_AVAILABLE_ private compile definitions, and reexporting them in
  1100. # the interface compile definitions.
  1101. _juce_get_module_definitions(${target} ON enabled_modules)
  1102. target_compile_definitions(${target} INTERFACE ${enabled_modules})
  1103. target_compile_definitions(${target} PRIVATE JUCE_SHARED_CODE=1)
  1104. get_target_property(project_version_string ${target} JUCE_VERSION)
  1105. _juce_version_code(${project_version_string} project_version_hex)
  1106. get_target_property(project_manufacturer_code ${target} JUCE_PLUGIN_MANUFACTURER_CODE)
  1107. get_target_property(project_plugin_code ${target} JUCE_PLUGIN_CODE)
  1108. get_target_property(use_legacy_compatibility_plugin_code ${target} JUCE_USE_LEGACY_COMPATIBILITY_PLUGIN_CODE)
  1109. if(use_legacy_compatibility_plugin_code)
  1110. set(project_manufacturer_code "proj")
  1111. endif()
  1112. _juce_to_char_literal(${project_manufacturer_code} project_manufacturer_code "plugin manufacturer")
  1113. _juce_to_char_literal(${project_plugin_code} project_plugin_code "plugin")
  1114. _juce_get_vst3_category_string(${target} vst3_category_string)
  1115. target_compile_definitions(${target} PUBLIC
  1116. JUCE_STANDALONE_APPLICATION=JucePlugin_Build_Standalone
  1117. JucePlugin_IsSynth=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_SYNTH>>
  1118. JucePlugin_ManufacturerCode=0x${project_manufacturer_code}
  1119. JucePlugin_Manufacturer="$<TARGET_PROPERTY:${target},JUCE_COMPANY_NAME>"
  1120. JucePlugin_ManufacturerWebsite="$<TARGET_PROPERTY:${target},JUCE_COMPANY_WEBSITE>"
  1121. JucePlugin_ManufacturerEmail="$<TARGET_PROPERTY:${target},JUCE_COMPANY_EMAIL>"
  1122. JucePlugin_PluginCode=0x${project_plugin_code}
  1123. JucePlugin_ProducesMidiOutput=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_NEEDS_MIDI_OUTPUT>>
  1124. JucePlugin_IsMidiEffect=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_MIDI_EFFECT>>
  1125. JucePlugin_WantsMidiInput=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_NEEDS_MIDI_INPUT>>
  1126. JucePlugin_EditorRequiresKeyboardFocus=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_EDITOR_WANTS_KEYBOARD_FOCUS>>
  1127. JucePlugin_Name="$<TARGET_PROPERTY:${target},JUCE_PLUGIN_NAME>"
  1128. JucePlugin_Desc="$<TARGET_PROPERTY:${target},JUCE_DESCRIPTION>"
  1129. JucePlugin_Version=${project_version_string}
  1130. JucePlugin_VersionString="${project_version_string}"
  1131. JucePlugin_VersionCode=${project_version_hex}
  1132. JucePlugin_VSTUniqueID=JucePlugin_PluginCode
  1133. JucePlugin_VSTCategory=$<TARGET_PROPERTY:${target},JUCE_VST2_CATEGORY>
  1134. JucePlugin_Vst3Category="${vst3_category_string}"
  1135. JucePlugin_AUMainType=$<TARGET_PROPERTY:${target},JUCE_AU_MAIN_TYPE_CODE>
  1136. JucePlugin_AUSubType=JucePlugin_PluginCode
  1137. JucePlugin_AUExportPrefix=$<TARGET_PROPERTY:${target},JUCE_AU_EXPORT_PREFIX>
  1138. JucePlugin_AUExportPrefixQuoted="$<TARGET_PROPERTY:${target},JUCE_AU_EXPORT_PREFIX>"
  1139. JucePlugin_AUManufacturerCode=JucePlugin_ManufacturerCode
  1140. JucePlugin_CFBundleIdentifier=$<TARGET_PROPERTY:${target},JUCE_BUNDLE_ID>
  1141. JucePlugin_AAXIdentifier=$<TARGET_PROPERTY:${target},JUCE_AAX_IDENTIFIER>
  1142. JucePlugin_AAXManufacturerCode=JucePlugin_ManufacturerCode
  1143. JucePlugin_AAXProductId=JucePlugin_PluginCode
  1144. JucePlugin_AAXCategory=$<TARGET_PROPERTY:${target},JUCE_AAX_CATEGORY>
  1145. JucePlugin_AAXDisableBypass=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_BYPASS>>
  1146. JucePlugin_AAXDisableMultiMono=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_MULTI_MONO>>
  1147. JucePlugin_VSTNumMidiInputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_INS>
  1148. JucePlugin_VSTNumMidiOutputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_OUTS>
  1149. JucePlugin_Enable_ARA=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_ARA_EFFECT>>
  1150. JucePlugin_ARAFactoryID=$<TARGET_PROPERTY:${target},JUCE_ARA_FACTORY_ID>
  1151. JucePlugin_ARADocumentArchiveID=$<TARGET_PROPERTY:${target},JUCE_ARA_DOCUMENT_ARCHIVE_ID>
  1152. JucePlugin_ARACompatibleArchiveIDs=$<TARGET_PROPERTY:${target},JUCE_ARA_COMPATIBLE_ARCHIVE_IDS>
  1153. JucePlugin_ARAContentTypes=$<TARGET_PROPERTY:${target},JUCE_ARA_ANALYSIS_TYPES>
  1154. JucePlugin_ARATransformationFlags=$<TARGET_PROPERTY:${target},JUCE_ARA_TRANSFORMATION_FLAGS>)
  1155. set_target_properties(${target} PROPERTIES
  1156. POSITION_INDEPENDENT_CODE TRUE
  1157. INTERFACE_POSITION_INDEPENDENT_CODE TRUE
  1158. VISIBILITY_INLINES_HIDDEN TRUE
  1159. C_VISIBILITY_PRESET hidden
  1160. CXX_VISIBILITY_PRESET hidden)
  1161. # A convenience target for building all plugin variations at once
  1162. add_custom_target(${target}_All)
  1163. _juce_set_plugin_folder_property("${target}" "${target}_All")
  1164. foreach(kind IN LISTS active_formats)
  1165. _juce_link_plugin_wrapper(${target} ${kind})
  1166. if(TARGET ${target}_${kind})
  1167. list(APPEND active_plugin_targets ${target}_${kind})
  1168. endif()
  1169. endforeach()
  1170. set_target_properties(${target} PROPERTIES JUCE_ACTIVE_PLUGIN_TARGETS "${active_plugin_targets}")
  1171. if(TARGET ${target}_Standalone)
  1172. _juce_configure_app_bundle(${target} ${target}_Standalone)
  1173. endif()
  1174. if(TARGET ${target}_AAX)
  1175. target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk)
  1176. endif()
  1177. if((TARGET ${target}_AUv3) AND (TARGET ${target}_Standalone))
  1178. add_dependencies(${target}_Standalone ${target}_AUv3)
  1179. set_target_properties(${target}_Standalone PROPERTIES
  1180. XCODE_EMBED_APP_EXTENSIONS ${target}_AUv3)
  1181. endif()
  1182. get_target_property(wants_copy "${target}" JUCE_COPY_PLUGIN_AFTER_BUILD)
  1183. if(wants_copy)
  1184. juce_enable_copy_plugin_step("${target}")
  1185. endif()
  1186. endfunction()
  1187. # ==================================================================================================
  1188. function(_juce_set_generic_property_if_not_set target property)
  1189. list(LENGTH ARGN num_extra_args)
  1190. if(num_extra_args EQUAL 0)
  1191. return()
  1192. endif()
  1193. set(existing_property)
  1194. get_target_property(existing_property ${target} ${property})
  1195. if(existing_property STREQUAL "existing_property-NOTFOUND")
  1196. set_target_properties(${target} PROPERTIES ${property} "${ARGN}")
  1197. endif()
  1198. endfunction()
  1199. function(_juce_set_property_if_not_set target property)
  1200. _juce_set_generic_property_if_not_set(${target} JUCE_${property} ${ARGN})
  1201. endfunction()
  1202. function(_juce_make_valid_4cc out_var)
  1203. string(RANDOM LENGTH 1 ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" head)
  1204. string(RANDOM LENGTH 3 ALPHABET "abcdefghijklmnopqrstuvwxyz" tail)
  1205. set(${out_var} "${head}${tail}" PARENT_SCOPE)
  1206. endfunction()
  1207. # This function adds some default properties that plugin targets expect to be
  1208. # set, in order to generate the correct compile definitions.
  1209. function(_juce_set_fallback_properties target)
  1210. _juce_set_property_if_not_set(${target} PRODUCT_NAME ${target})
  1211. get_target_property(output_name ${target} JUCE_PRODUCT_NAME)
  1212. _juce_set_property_if_not_set(${target} DESCRIPTION "${output_name}")
  1213. _juce_set_property_if_not_set(${target} PLUGIN_NAME "${output_name}")
  1214. get_target_property(real_company_name ${target} JUCE_COMPANY_NAME)
  1215. _juce_set_property_if_not_set(${target} BUNDLE_ID "com.${real_company_name}.${target}")
  1216. get_target_property(applied_bundle_id ${target} JUCE_BUNDLE_ID)
  1217. if("${applied_bundle_id}" MATCHES ".* .*")
  1218. message(WARNING "Target ${target} has JUCE_BUNDLE_ID '${applied_bundle_id}', which contains spaces. Use the BUNDLE_ID option to specify a valid ID.")
  1219. endif()
  1220. _juce_set_property_if_not_set(${target} VERSION ${PROJECT_VERSION})
  1221. get_target_property(final_version ${target} JUCE_VERSION)
  1222. if(NOT final_version)
  1223. message(FATAL_ERROR "Target ${target} must have its VERSION argument set, or must be part of a project with a PROJECT_VERSION")
  1224. endif()
  1225. _juce_set_property_if_not_set(${target} BUILD_VERSION "${final_version}")
  1226. get_target_property(custom_xcassets ${target} JUCE_CUSTOM_XCASSETS_FOLDER)
  1227. get_target_property(custom_storyboard ${target} JUCE_LAUNCH_STORYBOARD_FILE)
  1228. set(needs_storyboard TRUE)
  1229. if((NOT custom_storyboard) AND custom_xcassets AND (EXISTS "${custom_xcassets}/LaunchImage.launchimage"))
  1230. set(needs_storyboard FALSE)
  1231. endif()
  1232. set_target_properties(${target} PROPERTIES JUCE_SHOULD_ADD_STORYBOARD ${needs_storyboard})
  1233. _juce_set_property_if_not_set(${target} IPHONE_SCREEN_ORIENTATIONS
  1234. UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft
  1235. UIInterfaceOrientationLandscapeRight)
  1236. _juce_set_property_if_not_set(${target} IPAD_SCREEN_ORIENTATIONS
  1237. UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft
  1238. UIInterfaceOrientationLandscapeRight)
  1239. _juce_set_property_if_not_set(${target}
  1240. LAUNCH_STORYBOARD_FILE "${JUCE_CMAKE_UTILS_DIR}/LaunchScreen.storyboard")
  1241. _juce_set_property_if_not_set(${target} PLUGIN_MANUFACTURER_CODE "Manu")
  1242. # The plugin code will change on each run, unless you specify one manually!
  1243. _juce_make_valid_4cc(random_code)
  1244. _juce_set_property_if_not_set(${target} PLUGIN_CODE ${random_code})
  1245. _juce_set_property_if_not_set(${target} IS_SYNTH FALSE)
  1246. _juce_set_property_if_not_set(${target} NEEDS_MIDI_INPUT FALSE)
  1247. _juce_set_property_if_not_set(${target} NEEDS_MIDI_OUTPUT FALSE)
  1248. _juce_set_property_if_not_set(${target} IS_MIDI_EFFECT FALSE)
  1249. _juce_set_property_if_not_set(${target} EDITOR_WANTS_KEYBOARD_FOCUS FALSE)
  1250. _juce_set_property_if_not_set(${target} DISABLE_AAX_BYPASS FALSE)
  1251. _juce_set_property_if_not_set(${target} DISABLE_AAX_MULTI_MONO FALSE)
  1252. _juce_set_property_if_not_set(${target} PLUGINHOST_AU FALSE)
  1253. get_target_property(bundle_id ${target} JUCE_BUNDLE_ID)
  1254. _juce_set_property_if_not_set(${target} AAX_IDENTIFIER ${bundle_id})
  1255. _juce_set_property_if_not_set(${target} VST_NUM_MIDI_INS 16)
  1256. _juce_set_property_if_not_set(${target} VST_NUM_MIDI_OUTS 16)
  1257. _juce_set_property_if_not_set(${target} AU_SANDBOX_SAFE FALSE)
  1258. _juce_set_property_if_not_set(${target} SUPPRESS_AU_PLIST_RESOURCE_USAGE FALSE)
  1259. _juce_set_property_if_not_set(${target} HARDENED_RUNTIME_ENABLED FALSE)
  1260. _juce_set_property_if_not_set(${target} APP_SANDBOX_ENABLED FALSE)
  1261. _juce_set_property_if_not_set(${target} APP_SANDBOX_INHERIT FALSE)
  1262. _juce_set_property_if_not_set(${target} VST3_AUTO_MANIFEST TRUE)
  1263. get_target_property(is_synth ${target} JUCE_IS_SYNTH)
  1264. # VST3_CATEGORIES
  1265. if(is_synth)
  1266. _juce_set_property_if_not_set(${target} VST3_CATEGORIES Instrument Synth)
  1267. else()
  1268. _juce_set_property_if_not_set(${target} VST3_CATEGORIES Fx)
  1269. endif()
  1270. # VST2_CATEGORY
  1271. if(is_synth)
  1272. _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategSynth)
  1273. else()
  1274. _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategEffect)
  1275. endif()
  1276. get_target_property(is_midi_effect ${target} JUCE_IS_MIDI_EFFECT)
  1277. get_target_property(needs_midi_input ${target} JUCE_NEEDS_MIDI_INPUT)
  1278. # AU MAIN TYPE
  1279. if(is_midi_effect)
  1280. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MIDIProcessor)
  1281. elseif(is_synth)
  1282. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MusicDevice)
  1283. elseif(needs_midi_input)
  1284. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MusicEffect)
  1285. else()
  1286. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_Effect)
  1287. endif()
  1288. _juce_set_property_if_not_set(${target} TARGETED_DEVICE_FAMILY "1,2")
  1289. set(au_category_codes
  1290. 'aufx'
  1291. 'aufc'
  1292. 'augn'
  1293. 'aumi'
  1294. 'aumx'
  1295. 'aumu'
  1296. 'aumf'
  1297. 'auol'
  1298. 'auou'
  1299. 'aupn')
  1300. set(au_category_strings
  1301. kAudioUnitType_Effect
  1302. kAudioUnitType_FormatConverter
  1303. kAudioUnitType_Generator
  1304. kAudioUnitType_MIDIProcessor
  1305. kAudioUnitType_Mixer
  1306. kAudioUnitType_MusicDevice
  1307. kAudioUnitType_MusicEffect
  1308. kAudioUnitType_OfflineEffect
  1309. kAudioUnitType_Output
  1310. kAudioUnitType_Panner)
  1311. # AU export prefix
  1312. string(MAKE_C_IDENTIFIER ${output_name} au_prefix)
  1313. set(au_prefix "${au_prefix}AU")
  1314. _juce_set_property_if_not_set(${target} AU_EXPORT_PREFIX ${au_prefix})
  1315. # Find appropriate AU category code
  1316. get_target_property(actual_au_category ${target} JUCE_AU_MAIN_TYPE)
  1317. list(FIND au_category_strings ${actual_au_category} au_index)
  1318. if(au_index GREATER_EQUAL 0)
  1319. list(GET au_category_codes ${au_index} au_code_representation)
  1320. set_target_properties(${target} PROPERTIES JUCE_AU_MAIN_TYPE_CODE ${au_code_representation})
  1321. endif()
  1322. # AAX category
  1323. # The order of these strings is important, as the index of each string
  1324. # will be used to set an appropriate bit in the category bitfield.
  1325. set(aax_category_strings
  1326. ePlugInCategory_None
  1327. ePlugInCategory_EQ
  1328. ePlugInCategory_Dynamics
  1329. ePlugInCategory_PitchShift
  1330. ePlugInCategory_Reverb
  1331. ePlugInCategory_Delay
  1332. ePlugInCategory_Modulation
  1333. ePlugInCategory_Harmonic
  1334. ePlugInCategory_NoiseReduction
  1335. ePlugInCategory_Dither
  1336. ePlugInCategory_SoundField
  1337. ePlugInCategory_HWGenerators
  1338. ePlugInCategory_SWGenerators
  1339. ePlugInCategory_WrappedPlugin
  1340. ePlugInCategory_Effect)
  1341. if(is_synth)
  1342. set(default_aax_category ePlugInCategory_SWGenerators)
  1343. else()
  1344. set(default_aax_category ePlugInCategory_None)
  1345. endif()
  1346. _juce_set_property_if_not_set(${target} AAX_CATEGORY ${default_aax_category})
  1347. # Replace AAX category string with its integral representation
  1348. get_target_property(actual_aax_category ${target} JUCE_AAX_CATEGORY)
  1349. set(aax_category_int "")
  1350. foreach(category_string IN LISTS actual_aax_category)
  1351. list(FIND aax_category_strings ${category_string} aax_index)
  1352. if(aax_index GREATER_EQUAL 0)
  1353. if(aax_index EQUAL 0)
  1354. set(aax_category_bit 0)
  1355. else()
  1356. set(aax_category_bit "1 << (${aax_index} - 1)")
  1357. endif()
  1358. if(aax_category_int STREQUAL "")
  1359. set(aax_category_int 0)
  1360. endif()
  1361. math(EXPR aax_category_int "${aax_category_int} | (${aax_category_bit})")
  1362. endif()
  1363. endforeach()
  1364. if(NOT aax_category_int STREQUAL "")
  1365. set_target_properties(${target} PROPERTIES JUCE_AAX_CATEGORY ${aax_category_int})
  1366. endif()
  1367. # Ensure this matches the Projucer implementation
  1368. get_target_property(company_website ${target} JUCE_COMPANY_WEBSITE)
  1369. get_target_property(plugin_name ${target} JUCE_PLUGIN_NAME)
  1370. string(MAKE_C_IDENTIFIER "${plugin_name}" plugin_name_sanitised)
  1371. _juce_set_property_if_not_set(${target} LV2URI "${company_website}/plugins/${plugin_name_sanitised}")
  1372. # ARA configuration
  1373. # Analysis types
  1374. set(ara_analysis_type_strings
  1375. kARAContentTypeNotes
  1376. kARAContentTypeTempoEntries
  1377. kARAContentTypeBarSignatures
  1378. kARAContentTypeStaticTuning
  1379. kARAContentTypeKeySignatures
  1380. kARAContentTypeSheetChords)
  1381. get_target_property(actual_ara_analysis_types ${target} JUCE_ARA_ANALYSIS_TYPES)
  1382. set(ara_analysis_types_int "")
  1383. foreach(category_string IN LISTS actual_ara_analysis_types)
  1384. list(FIND ara_analysis_type_strings ${category_string} ara_index)
  1385. if(ara_index GREATER_EQUAL 0)
  1386. set(ara_analysis_types_bit "1 << ${ara_index}")
  1387. if(ara_analysis_types_int STREQUAL "")
  1388. set(ara_analysis_types_int 0)
  1389. endif()
  1390. math(EXPR ara_analysis_types_int "${ara_analysis_types_int} | (${ara_analysis_types_bit})")
  1391. endif()
  1392. endforeach()
  1393. if(NOT ara_analysis_types_int STREQUAL "")
  1394. set_target_properties(${target} PROPERTIES JUCE_ARA_ANALYSIS_TYPES ${ara_analysis_types_int})
  1395. endif()
  1396. _juce_set_property_if_not_set(${target} ARA_ANALYSIS_TYPES 0)
  1397. # Transformation flags
  1398. set(ara_transformation_flags_strings
  1399. kARAPlaybackTransformationNoChanges
  1400. kARAPlaybackTransformationTimestretch
  1401. kARAPlaybackTransformationTimestretchReflectingTempo
  1402. kARAPlaybackTransformationContentBasedFadeAtTail
  1403. kARAPlaybackTransformationContentBasedFadeAtHead)
  1404. set(default_ara_transformation_flags kARAPlaybackTransformationNoChanges)
  1405. _juce_set_property_if_not_set(${target} ARA_TRANSFORMATION_FLAGS ${default_ara_transformation_flags})
  1406. get_target_property(actual_ara_transformation_flags ${target} JUCE_ARA_TRANSFORMATION_FLAGS)
  1407. set(ara_transformation_flags_int "")
  1408. foreach(transformation_string IN LISTS actual_ara_transformation_flags)
  1409. list(FIND ara_transformation_flags_strings ${transformation_string} ara_transformation_index)
  1410. if(ara_transformation_index GREATER_EQUAL 0)
  1411. if(ara_transformation_index EQUAL 0)
  1412. set(ara_transformation_bit 0)
  1413. else()
  1414. set(ara_transformation_bit "1 << (${ara_transformation_index} - 1)")
  1415. endif()
  1416. if(ara_transformation_flags_int STREQUAL "")
  1417. set(ara_transformation_flags_int 0)
  1418. endif()
  1419. math(EXPR ara_transformation_flags_int "${ara_transformation_flags_int} | (${ara_transformation_bit})")
  1420. endif()
  1421. endforeach()
  1422. if(NOT ara_transformation_flags_int STREQUAL "")
  1423. set_target_properties(${target} PROPERTIES JUCE_ARA_TRANSFORMATION_FLAGS ${ara_transformation_flags_int})
  1424. endif()
  1425. _juce_set_property_if_not_set(${target} IS_ARA_EFFECT FALSE)
  1426. get_target_property(final_bundle_id ${target} JUCE_BUNDLE_ID)
  1427. _juce_set_property_if_not_set(${target} ARA_FACTORY_ID "\"${final_bundle_id}.arafactory.${final_version}\"")
  1428. _juce_set_property_if_not_set(${target} ARA_DOCUMENT_ARCHIVE_ID "\"${final_bundle_id}.aradocumentarchive.1\"")
  1429. _juce_set_property_if_not_set(${target} ARA_COMPATIBLE_ARCHIVE_IDS "\"\"")
  1430. endfunction()
  1431. # ==================================================================================================
  1432. function(_juce_initialise_target target)
  1433. set(one_value_args
  1434. VERSION
  1435. BUILD_VERSION
  1436. PRODUCT_NAME
  1437. PLIST_TO_MERGE
  1438. BUNDLE_ID
  1439. MICROPHONE_PERMISSION_ENABLED
  1440. MICROPHONE_PERMISSION_TEXT
  1441. CAMERA_PERMISSION_ENABLED
  1442. CAMERA_PERMISSION_TEXT
  1443. SEND_APPLE_EVENTS_PERMISSION_ENABLED
  1444. SEND_APPLE_EVENTS_PERMISSION_TEXT
  1445. BLUETOOTH_PERMISSION_ENABLED
  1446. BLUETOOTH_PERMISSION_TEXT
  1447. FILE_SHARING_ENABLED # iOS only
  1448. DOCUMENT_BROWSER_ENABLED # iOS only
  1449. LAUNCH_STORYBOARD_FILE # iOS only
  1450. APP_GROUPS_ENABLED # iOS only
  1451. ICLOUD_PERMISSIONS_ENABLED # iOS only
  1452. STATUS_BAR_HIDDEN # iOS only
  1453. BACKGROUND_AUDIO_ENABLED # iOS only
  1454. BACKGROUND_BLE_ENABLED # iOS only
  1455. CUSTOM_XCASSETS_FOLDER # iOS only
  1456. TARGETED_DEVICE_FAMILY # iOS only
  1457. REQUIRES_FULL_SCREEN # iOS only
  1458. ICON_BIG
  1459. ICON_SMALL
  1460. COMPANY_COPYRIGHT
  1461. COMPANY_NAME
  1462. COMPANY_WEBSITE
  1463. COMPANY_EMAIL
  1464. NEEDS_CURL # Set this true if you want to link curl on Linux
  1465. NEEDS_WEB_BROWSER # Set this true if you want to link webkit on Linux
  1466. NEEDS_STORE_KIT # Set this true if you want in-app-purchases on Mac
  1467. PUSH_NOTIFICATIONS_ENABLED
  1468. NETWORK_MULTICAST_ENABLED
  1469. HARDENED_RUNTIME_ENABLED
  1470. APP_SANDBOX_ENABLED
  1471. APP_SANDBOX_INHERIT
  1472. VST3_AUTO_MANIFEST
  1473. PLUGIN_NAME
  1474. PLUGIN_MANUFACTURER_CODE
  1475. PLUGIN_CODE
  1476. DESCRIPTION
  1477. IS_SYNTH
  1478. NEEDS_MIDI_INPUT
  1479. NEEDS_MIDI_OUTPUT
  1480. IS_MIDI_EFFECT
  1481. EDITOR_WANTS_KEYBOARD_FOCUS
  1482. DISABLE_AAX_BYPASS
  1483. DISABLE_AAX_MULTI_MONO
  1484. AAX_IDENTIFIER
  1485. VST_NUM_MIDI_INS
  1486. VST_NUM_MIDI_OUTS
  1487. VST2_CATEGORY
  1488. AU_MAIN_TYPE
  1489. AU_EXPORT_PREFIX
  1490. AU_SANDBOX_SAFE
  1491. SUPPRESS_AU_PLIST_RESOURCE_USAGE
  1492. PLUGINHOST_AU # Set this true if you want to host AU plugins
  1493. USE_LEGACY_COMPATIBILITY_PLUGIN_CODE
  1494. LV2URI
  1495. IS_ARA_EFFECT
  1496. ARA_FACTORY_ID
  1497. ARA_DOCUMENT_ARCHIVE_ID
  1498. VST_COPY_DIR
  1499. VST3_COPY_DIR
  1500. AAX_COPY_DIR
  1501. AU_COPY_DIR
  1502. UNITY_COPY_DIR
  1503. COPY_PLUGIN_AFTER_BUILD)
  1504. set(multi_value_args
  1505. FORMATS
  1506. VST3_CATEGORIES
  1507. HARDENED_RUNTIME_OPTIONS
  1508. APP_SANDBOX_OPTIONS
  1509. APP_SANDBOX_FILE_ACCESS_HOME_RO
  1510. APP_SANDBOX_FILE_ACCESS_HOME_RW
  1511. APP_SANDBOX_FILE_ACCESS_ABS_RO
  1512. APP_SANDBOX_FILE_ACCESS_ABS_RW
  1513. APP_SANDBOX_EXCEPTION_IOKIT
  1514. DOCUMENT_EXTENSIONS
  1515. AAX_CATEGORY
  1516. IPHONE_SCREEN_ORIENTATIONS # iOS only
  1517. IPAD_SCREEN_ORIENTATIONS # iOS only
  1518. APP_GROUP_IDS # iOS only
  1519. ARA_COMPATIBLE_ARCHIVE_IDS
  1520. ARA_ANALYSIS_TYPES
  1521. ARA_TRANSFORMATION_FLAGS)
  1522. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
  1523. set(base_folder "${CMAKE_CURRENT_BINARY_DIR}/${target}_artefacts")
  1524. set(products_folder "${base_folder}/$<CONFIG>")
  1525. set(juce_library_code "${base_folder}/JuceLibraryCode")
  1526. set_target_properties(${target} PROPERTIES JUCE_GENERATED_SOURCES_DIRECTORY "${juce_library_code}")
  1527. set_target_properties(${target} PROPERTIES
  1528. ARCHIVE_OUTPUT_DIRECTORY "${products_folder}"
  1529. LIBRARY_OUTPUT_DIRECTORY "${products_folder}"
  1530. RUNTIME_OUTPUT_DIRECTORY "${products_folder}")
  1531. if(JUCE_ARG_ICON_BIG)
  1532. _juce_make_absolute_and_check(JUCE_ARG_ICON_BIG)
  1533. endif()
  1534. if(JUCE_ARG_ICON_SMALL)
  1535. _juce_make_absolute_and_check(JUCE_ARG_ICON_SMALL)
  1536. endif()
  1537. set(inherited_properties
  1538. COMPANY_NAME
  1539. COMPANY_WEBSITE
  1540. COMPANY_EMAIL
  1541. COMPANY_COPYRIGHT
  1542. VST_COPY_DIR
  1543. VST3_COPY_DIR
  1544. AU_COPY_DIR
  1545. AAX_COPY_DIR
  1546. UNITY_COPY_DIR
  1547. COPY_PLUGIN_AFTER_BUILD)
  1548. # Overwrite any properties that might be inherited
  1549. foreach(prop_string IN LISTS inherited_properties)
  1550. if(NOT ${JUCE_ARG_${prop_string}} STREQUAL "")
  1551. set_target_properties(${target} PROPERTIES JUCE_${prop_string} "${JUCE_ARG_${prop_string}}")
  1552. endif()
  1553. endforeach()
  1554. # Add each of the function arguments as target properties, so that it's easier to
  1555. # extract them in other functions
  1556. foreach(arg_string IN LISTS one_value_args multi_value_args)
  1557. _juce_set_property_if_not_set(${target} ${arg_string} "${JUCE_ARG_${arg_string}}")
  1558. endforeach()
  1559. _juce_set_fallback_properties(${target})
  1560. target_include_directories(${target} PRIVATE
  1561. $<TARGET_PROPERTY:${target},JUCE_GENERATED_SOURCES_DIRECTORY>)
  1562. target_link_libraries(${target} PUBLIC $<$<TARGET_EXISTS:juce_vst2_sdk>:juce_vst2_sdk>)
  1563. get_target_property(is_pluginhost_au ${target} JUCE_PLUGINHOST_AU)
  1564. if(is_pluginhost_au)
  1565. target_compile_definitions(${target} PUBLIC JUCE_PLUGINHOST_AU=1)
  1566. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
  1567. _juce_link_frameworks("${target}" PRIVATE CoreAudioKit)
  1568. endif()
  1569. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  1570. _juce_link_frameworks("${target}" PRIVATE AudioUnit)
  1571. endif()
  1572. endif()
  1573. _juce_write_generate_time_info(${target})
  1574. _juce_link_optional_libraries(${target})
  1575. _juce_fixup_module_source_groups()
  1576. endfunction()
  1577. # ==================================================================================================
  1578. function(juce_add_console_app target)
  1579. # The _NO_RESOURCERC option is private, and is only intended for use when building juceaide.
  1580. # We can't add a resources.rc to juceaide because we need juceaide to generate the resources.rc!
  1581. cmake_parse_arguments(JUCE_ARG "_NO_RESOURCERC" "" "" ${ARGN})
  1582. add_executable(${target})
  1583. target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1)
  1584. if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  1585. target_compile_definitions(${target} PRIVATE _CONSOLE=1)
  1586. endif()
  1587. _juce_initialise_target(${target} ${ARGN})
  1588. if(NOT JUCE_ARG__NO_RESOURCERC)
  1589. _juce_write_configure_time_info(${target})
  1590. _juce_add_resources_rc(${target} ${target})
  1591. endif()
  1592. endfunction()
  1593. function(juce_add_gui_app target)
  1594. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  1595. add_library(${target} SHARED)
  1596. else()
  1597. add_executable(${target})
  1598. endif()
  1599. target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1)
  1600. _juce_initialise_target(${target} ${ARGN})
  1601. _juce_set_output_name(${target} $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>)
  1602. set_target_properties(${target} PROPERTIES JUCE_TARGET_KIND_STRING "App")
  1603. _juce_configure_bundle(${target} ${target})
  1604. _juce_configure_app_bundle(${target} ${target})
  1605. _juce_add_resources_rc(${target} ${target})
  1606. endfunction()
  1607. function(juce_add_plugin target)
  1608. add_library(${target} STATIC)
  1609. set_target_properties(${target} PROPERTIES JUCE_IS_PLUGIN TRUE)
  1610. _juce_initialise_target(${target} ${ARGN})
  1611. _juce_configure_plugin_targets(${target})
  1612. endfunction()
  1613. # ==================================================================================================
  1614. function(_juce_target_args_from_plugin_characteristics out_var)
  1615. set(pairs
  1616. "pluginIsSynth\;IS_SYNTH"
  1617. "pluginWantsMidiIn\;NEEDS_MIDI_INPUT"
  1618. "pluginProducesMidiOut\;NEEDS_MIDI_OUTPUT"
  1619. "pluginIsMidiEffectPlugin\;IS_MIDI_EFFECT"
  1620. "pluginEditorRequiresKeys\;EDITOR_WANTS_KEYBOARD_FOCUS")
  1621. set(result)
  1622. foreach(pair IN LISTS pairs)
  1623. list(GET pair 0 old_key)
  1624. if("${old_key}" IN_LIST ARGN)
  1625. list(GET pair 1 new_key)
  1626. list(APPEND result ${new_key} TRUE)
  1627. endif()
  1628. endforeach()
  1629. set(${out_var} ${result} PARENT_SCOPE)
  1630. endfunction()
  1631. # ==================================================================================================
  1632. function(_juce_get_pip_targets pip out_var)
  1633. set(test_targets "${pip}")
  1634. _juce_get_all_plugin_kinds(plugin_kinds)
  1635. foreach(plugin_kind IN LISTS plugin_kinds)
  1636. list(APPEND test_targets "${JUCE_PIP_NAME}_${plugin_kind}")
  1637. endforeach()
  1638. set(${out_var} ${test_targets} PARENT_SCOPE)
  1639. endfunction()
  1640. function(juce_add_pip header)
  1641. _juce_make_absolute(header)
  1642. _juce_extract_metadata_block(JUCE_PIP_METADATA "${header}" metadata_dict)
  1643. _juce_get_metadata("${metadata_dict}" name JUCE_PIP_NAME)
  1644. if(NOT JUCE_PIP_NAME)
  1645. message(FATAL_ERROR "Error in '${header}': PIP headers must declare a `name` field")
  1646. endif()
  1647. string(MAKE_C_IDENTIFIER "${JUCE_PIP_NAME}" pip_name_sanitised)
  1648. if(NOT JUCE_PIP_NAME STREQUAL pip_name_sanitised)
  1649. message(FATAL_ERROR "Error in '${header}': PIP `name` value '${JUCE_PIP_NAME}' must be a valid C identifier")
  1650. endif()
  1651. if(TARGET "${JUCE_PIP_NAME}")
  1652. # We already added a target with this name, let's try using the filename instead
  1653. get_filename_component(JUCE_PIP_NAME "${header}" NAME_WE)
  1654. endif()
  1655. if(TARGET "${JUCE_PIP_NAME}")
  1656. message(FATAL_ERROR "Error in '${header}': Could not create a unique target name for PIP ${header}")
  1657. endif()
  1658. _juce_get_metadata("${metadata_dict}" type pip_kind)
  1659. if(NOT pip_kind)
  1660. message(FATAL_ERROR "Error in '${header}': PIP headers must declare a `type` field")
  1661. endif()
  1662. _juce_get_metadata("${metadata_dict}" pluginCharacteristics pip_charateristics)
  1663. _juce_target_args_from_plugin_characteristics(extra_target_args ${pip_charateristics})
  1664. list(APPEND extra_target_args
  1665. NEEDS_CURL TRUE
  1666. NEEDS_WEB_BROWSER TRUE)
  1667. _juce_get_metadata("${metadata_dict}" moduleFlags pip_moduleflags)
  1668. if("JUCE_IN_APP_PURCHASES=1" IN_LIST pip_moduleflags)
  1669. list(APPEND extra_target_args
  1670. BUNDLE_ID "com.rmsl.juceInAppPurchaseSample"
  1671. NEEDS_STORE_KIT TRUE)
  1672. endif()
  1673. if("JUCE_PLUGINHOST_AU=1" IN_LIST pip_moduleflags)
  1674. list(APPEND extra_target_args PLUGINHOST_AU TRUE)
  1675. endif()
  1676. if(pip_kind STREQUAL "AudioProcessor")
  1677. _juce_get_metadata("${metadata_dict}" documentControllerClass JUCE_PIP_DOCUMENTCONTROLLER_CLASS)
  1678. if(JUCE_PIP_DOCUMENTCONTROLLER_CLASS)
  1679. if(NOT TARGET juce_ara_sdk)
  1680. message(WARNING
  1681. "${header} specifies a documentControllerClass, but the ARA SDK could not be located. "
  1682. "Use juce_set_ara_sdk_path to specify the ARA SDK location. "
  1683. "This PIP will not be configured.")
  1684. endif()
  1685. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessorWithARA.cpp.in")
  1686. juce_add_plugin(${JUCE_PIP_NAME}
  1687. FORMATS AU VST3
  1688. IS_ARA_EFFECT TRUE
  1689. ${extra_target_args})
  1690. else()
  1691. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in")
  1692. # We add AAX/VST2 targets too, if the user has set up those SDKs
  1693. set(extra_formats)
  1694. if(TARGET juce_aax_sdk)
  1695. list(APPEND extra_formats AAX)
  1696. endif()
  1697. if(TARGET juce_vst2_sdk)
  1698. list(APPEND extra_formats VST)
  1699. endif()
  1700. if(NOT (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  1701. list(APPEND extra_formats VST3)
  1702. endif()
  1703. # Standalone plugins might want to access the mic
  1704. list(APPEND extra_target_args MICROPHONE_PERMISSION_ENABLED TRUE)
  1705. juce_add_plugin(${JUCE_PIP_NAME}
  1706. FORMATS AU AUv3 LV2 Standalone Unity ${extra_formats}
  1707. ${extra_target_args})
  1708. endif()
  1709. elseif(pip_kind STREQUAL "Component")
  1710. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPComponent.cpp.in")
  1711. juce_add_gui_app(${JUCE_PIP_NAME} ${extra_target_args})
  1712. elseif(pip_kind STREQUAL "Console")
  1713. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPConsole.cpp.in")
  1714. juce_add_console_app(${JUCE_PIP_NAME} ${extra_target_args})
  1715. else()
  1716. message(FATAL_ERROR "Error in '${header}': PIP kind must be either AudioProcessor, Component, or Console")
  1717. endif()
  1718. if(NOT ARGV1 STREQUAL "")
  1719. set("${ARGV1}" "${JUCE_PIP_NAME}" PARENT_SCOPE)
  1720. endif()
  1721. # Generate Main.cpp
  1722. _juce_get_metadata("${metadata_dict}" mainClass JUCE_PIP_MAIN_CLASS)
  1723. get_target_property(juce_library_code ${JUCE_PIP_NAME} JUCE_GENERATED_SOURCES_DIRECTORY)
  1724. set(pip_main "${juce_library_code}/Main.cpp")
  1725. set(JUCE_PIP_HEADER "${header}")
  1726. configure_file(${source_main} ${pip_main})
  1727. target_sources(${JUCE_PIP_NAME} PRIVATE ${pip_main})
  1728. _juce_get_metadata("${metadata_dict}" dependencies pip_dependencies)
  1729. juce_generate_juce_header(${JUCE_PIP_NAME})
  1730. foreach(module IN LISTS pip_dependencies)
  1731. if(module STREQUAL "")
  1732. continue()
  1733. endif()
  1734. set(discovered_module)
  1735. if(TARGET "${module}")
  1736. set(discovered_module "${module}")
  1737. else()
  1738. message(FATAL_ERROR "Error in '${header}': No such module: ${module}")
  1739. endif()
  1740. target_link_libraries(${JUCE_PIP_NAME} PRIVATE ${discovered_module})
  1741. endforeach()
  1742. target_compile_definitions(${JUCE_PIP_NAME}
  1743. PRIVATE ${pip_moduleflags}
  1744. PUBLIC
  1745. JUCE_VST3_CAN_REPLACE_VST2=0)
  1746. _juce_get_pip_targets(${JUCE_PIP_NAME} pip_targets)
  1747. # This keeps the PIPs slightly better organised in the JUCE megaproject
  1748. if((DEFINED JUCE_SOURCE_DIR) AND (header MATCHES "^${JUCE_SOURCE_DIR}"))
  1749. file(RELATIVE_PATH folder "${JUCE_SOURCE_DIR}" "${header}")
  1750. get_filename_component(folder_parent "${folder}" DIRECTORY)
  1751. foreach(target_name IN ITEMS ${pip_targets} ${JUCE_PIP_NAME}_All)
  1752. if(TARGET "${target_name}")
  1753. set_target_properties("${target_name}" PROPERTIES
  1754. FOLDER "${folder_parent}/${JUCE_PIP_NAME}")
  1755. endif()
  1756. endforeach()
  1757. endif()
  1758. # We're building JUCE itself
  1759. if(DEFINED JUCE_SOURCE_DIR)
  1760. # PIPs need to know about the resources folder
  1761. target_compile_definitions(${JUCE_PIP_NAME} PRIVATE
  1762. PIP_JUCE_EXAMPLES_DIRECTORY_STRING="${JUCE_SOURCE_DIR}/examples")
  1763. get_filename_component(pip_parent_path "${header}" DIRECTORY)
  1764. target_include_directories(${JUCE_PIP_NAME} PRIVATE "${pip_parent_path}")
  1765. if((CMAKE_SYSTEM_NAME STREQUAL "iOS") AND (header MATCHES "^${JUCE_SOURCE_DIR}"))
  1766. foreach(target_name IN LISTS pip_targets)
  1767. if(TARGET "${target_name}")
  1768. juce_add_bundle_resources_directory("${target_name}" "${JUCE_SOURCE_DIR}/examples/Assets")
  1769. endif()
  1770. endforeach()
  1771. endif()
  1772. if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") OR (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
  1773. target_compile_options(${JUCE_PIP_NAME} PRIVATE /bigobj)
  1774. endif()
  1775. endif()
  1776. endfunction()
  1777. # ==================================================================================================
  1778. function(juce_set_aax_sdk_path path)
  1779. if(TARGET juce_aax_sdk)
  1780. message(FATAL_ERROR "juce_set_aax_sdk_path should only be called once")
  1781. endif()
  1782. _juce_make_absolute(path)
  1783. if((NOT EXISTS "${path}")
  1784. OR (NOT EXISTS "${path}/Interfaces")
  1785. OR (NOT EXISTS "${path}/Interfaces/ACF"))
  1786. message(FATAL_ERROR "Could not find AAX SDK at the specified path: ${path}")
  1787. endif()
  1788. if((CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR (CMAKE_SYSTEM_NAME STREQUAL "Windows"))
  1789. add_library(juce_aax_sdk INTERFACE IMPORTED GLOBAL)
  1790. else()
  1791. return()
  1792. endif()
  1793. target_include_directories(juce_aax_sdk INTERFACE
  1794. "${path}"
  1795. "${path}/Interfaces"
  1796. "${path}/Interfaces/ACF")
  1797. set_target_properties(juce_aax_sdk PROPERTIES INTERFACE_JUCE_AAX_DEFAULT_ICON "${path}/Utilities/PlugIn.ico")
  1798. endfunction()
  1799. function(juce_set_vst2_sdk_path path)
  1800. if(TARGET juce_vst2_sdk)
  1801. message(FATAL_ERROR "juce_set_vst2_sdk_path should only be called once")
  1802. endif()
  1803. _juce_make_absolute(path)
  1804. if(NOT EXISTS "${path}")
  1805. message(FATAL_ERROR "Could not find VST2 SDK at the specified path: ${path}")
  1806. endif()
  1807. add_library(juce_vst2_sdk INTERFACE IMPORTED GLOBAL)
  1808. # This is a bit of a hack, but we really need the VST2 paths to always follow the VST3 paths.
  1809. target_include_directories(juce_vst2_sdk INTERFACE
  1810. $<TARGET_PROPERTY:juce::juce_vst3_headers,INTERFACE_INCLUDE_DIRECTORIES>
  1811. "${path}")
  1812. endfunction()
  1813. function(juce_set_vst3_sdk_path path)
  1814. if(TARGET juce_vst3_sdk)
  1815. message(FATAL_ERROR "juce_set_vst3_sdk_path should only be called once")
  1816. endif()
  1817. _juce_make_absolute(path)
  1818. if(NOT EXISTS "${path}")
  1819. message(FATAL_ERROR "Could not find VST3 SDK at the specified path: ${path}")
  1820. endif()
  1821. add_library(juce_vst3_sdk INTERFACE IMPORTED GLOBAL)
  1822. target_include_directories(juce_vst3_sdk INTERFACE "${path}")
  1823. endfunction()
  1824. function(juce_set_ara_sdk_path path)
  1825. if(TARGET juce_ara_sdk)
  1826. message(FATAL_ERROR "juce_set_ara_sdk_path should only be called once")
  1827. endif()
  1828. _juce_make_absolute(path)
  1829. if(NOT EXISTS "${path}")
  1830. message(FATAL_ERROR "Could not find ARA SDK at the specified path: ${path}")
  1831. endif()
  1832. add_library(juce_ara_sdk INTERFACE IMPORTED GLOBAL)
  1833. target_include_directories(juce_ara_sdk INTERFACE "${path}")
  1834. endfunction()
  1835. # ==================================================================================================
  1836. function(juce_disable_default_flags)
  1837. set(langs C CXX)
  1838. set(modes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
  1839. foreach(lang IN LISTS langs)
  1840. foreach(mode IN LISTS modes)
  1841. list(FILTER CMAKE_${lang}_FLAGS_${mode} INCLUDE REGEX "[/-]M[TD]d?")
  1842. set(CMAKE_${lang}_FLAGS_${mode} "${CMAKE_${lang}_FLAGS_${mode}}" PARENT_SCOPE)
  1843. endforeach()
  1844. endforeach()
  1845. endfunction()