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.

2457 lines
98KB

  1. # ==============================================================================
  2. #
  3. # This file is part of the JUCE library.
  4. # Copyright (c) 2020 - 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 6 End-User License
  10. # Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  11. #
  12. # End User License Agreement: www.juce.com/juce-6-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/CMake Compatibility Module
  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.12)
  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_COPY_PLUGIN_AFTER_BUILD INHERITED
  67. BRIEF_DOCS "Whether or not plugins should be copied after building"
  68. FULL_DOCS "Whether or not plugins should be copied after building")
  69. set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE)
  70. # ==================================================================================================
  71. function(_juce_add_interface_library target)
  72. add_library(${target} INTERFACE)
  73. target_sources(${target} INTERFACE ${ARGN})
  74. endfunction()
  75. # ==================================================================================================
  76. function(_juce_create_pkgconfig_target name)
  77. if(TARGET juce::pkgconfig_${name})
  78. return()
  79. endif()
  80. find_package(PkgConfig REQUIRED)
  81. pkg_check_modules(${name} ${ARGN})
  82. add_library(pkgconfig_${name} INTERFACE)
  83. add_library(juce::pkgconfig_${name} ALIAS pkgconfig_${name})
  84. install(TARGETS pkgconfig_${name} EXPORT JUCE)
  85. set(pairs
  86. "INCLUDE_DIRECTORIES\;INCLUDE_DIRS"
  87. "LINK_LIBRARIES\;LINK_LIBRARIES"
  88. "LINK_OPTIONS\;LDFLAGS_OTHER"
  89. "COMPILE_OPTIONS\;CFLAGS_OTHER")
  90. foreach(pair IN LISTS pairs)
  91. list(GET pair 0 key)
  92. list(GET pair 1 value)
  93. if(${name}_${value})
  94. set_target_properties(pkgconfig_${name} PROPERTIES INTERFACE_${key} "${${name}_${value}}")
  95. endif()
  96. endforeach()
  97. endfunction()
  98. # ==================================================================================================
  99. set(JUCE_CMAKE_UTILS_DIR ${CMAKE_CURRENT_LIST_DIR}
  100. CACHE INTERNAL "The path to the folder holding this file and other resources")
  101. include("${JUCE_CMAKE_UTILS_DIR}/JUCEHelperTargets.cmake")
  102. include("${JUCE_CMAKE_UTILS_DIR}/JUCECheckAtomic.cmake")
  103. _juce_create_atomic_target(juce_atomic_wrapper)
  104. # Tries to discover the target platform architecture, which is necessary for
  105. # naming VST3 bundle folders correctly.
  106. function(_juce_find_linux_target_architecture result)
  107. set(test_file "${JUCE_CMAKE_UTILS_DIR}/juce_runtime_arch_detection.cpp")
  108. try_compile(compile_result "${CMAKE_CURRENT_BINARY_DIR}" "${test_file}"
  109. OUTPUT_VARIABLE compile_output)
  110. string(REGEX REPLACE ".*JUCE_ARCH ([a-zA-Z0-9_-]*).*" "\\1" match_result "${compile_output}")
  111. set("${result}" "${match_result}" PARENT_SCOPE)
  112. endfunction()
  113. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  114. _juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl)
  115. _juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0)
  116. # If you really need to override the detected arch for some reason,
  117. # you can configure the build with -DJUCE_LINUX_TARGET_ARCHITECTURE=<custom arch>
  118. if(NOT DEFINED JUCE_LINUX_TARGET_ARCHITECTURE)
  119. _juce_find_linux_target_architecture(target_arch)
  120. set(JUCE_LINUX_TARGET_ARCHITECTURE "${target_arch}"
  121. CACHE INTERNAL "The target architecture, used to name internal folders in VST3 bundles")
  122. endif()
  123. elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  124. find_program(JUCE_XCRUN xcrun)
  125. if(NOT JUCE_XCRUN)
  126. message(WARNING "failed to find xcrun; older resource-based AU plug-ins may not work correctly")
  127. endif()
  128. endif()
  129. # We set up default/fallback copy dirs here. If you need different copy dirs, use
  130. # set_directory_properties or set_target_properties to adjust the values of `JUCE_*_COPY_DIR` at
  131. # the appropriate scope.
  132. function(_juce_set_default_properties)
  133. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  134. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST")
  135. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3")
  136. set_property(GLOBAL PROPERTY JUCE_AU_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components")
  137. set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "/Library/Application Support/Avid/Audio/Plug-Ins")
  138. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  139. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  140. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{ProgramW6432}/Steinberg/Vstplugins")
  141. set(prefix "$ENV{CommonProgramW6432}")
  142. else()
  143. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{programfiles\(x86\)}/Steinberg/Vstplugins")
  144. set(prefix "$ENV{CommonProgramFiles\(x86\)}")
  145. endif()
  146. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "${prefix}/VST3")
  147. set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "${prefix}/Avid/Audio/Plug-Ins")
  148. elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  149. set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/.vst")
  150. set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/.vst3")
  151. endif()
  152. endfunction()
  153. _juce_set_default_properties()
  154. # ==================================================================================================
  155. function(_juce_add_standard_defs juce_target)
  156. target_compile_definitions(${juce_target} INTERFACE
  157. JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1
  158. $<IF:$<CONFIG:DEBUG>,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1>
  159. $<$<PLATFORM_ID:Android>:JUCE_ANDROID=1>)
  160. endfunction()
  161. # ==================================================================================================
  162. macro(_juce_make_absolute path)
  163. if(NOT IS_ABSOLUTE "${${path}}")
  164. get_filename_component("${path}" "${${path}}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
  165. endif()
  166. endmacro()
  167. macro(_juce_make_absolute_and_check path)
  168. _juce_make_absolute("${path}")
  169. if(NOT EXISTS "${${path}}")
  170. message(FATAL_ERROR "No file at path ${${path}}")
  171. endif()
  172. endmacro()
  173. # ==================================================================================================
  174. function(juce_add_bundle_resources_directory target folder)
  175. _juce_make_absolute(folder)
  176. if(NOT EXISTS "${folder}")
  177. message(FATAL_ERROR "Could not find resource folder ${folder}")
  178. endif()
  179. get_filename_component(folder_parent_path "${folder}" DIRECTORY)
  180. file(GLOB_RECURSE resources RELATIVE "${folder_parent_path}" "${folder}/*")
  181. foreach(file IN LISTS resources)
  182. target_sources(${target} PRIVATE "${folder_parent_path}/${file}")
  183. get_filename_component(resource_parent_path "${file}" DIRECTORY)
  184. set_source_files_properties("${folder_parent_path}/${file}" PROPERTIES
  185. HEADER_FILE_ONLY TRUE
  186. MACOSX_PACKAGE_LOCATION "Resources/${resource_parent_path}")
  187. endforeach()
  188. endfunction()
  189. # ==================================================================================================
  190. # This creates an imported interface library with a random name, and then adds
  191. # the fields from a JUCE module header to the target as INTERFACE_ properties.
  192. # We can extract properties later using `_juce_get_metadata`.
  193. # This way, the interface library ends up behaving a bit like a dictionary,
  194. # and we don't have to parse the module header from scratch every time we
  195. # want to find a specific key.
  196. function(_juce_extract_metadata_block delim_str file_with_block out_dict)
  197. string(RANDOM LENGTH 16 random_string)
  198. set(target_name "${random_string}_dict")
  199. set(${out_dict} "${target_name}" PARENT_SCOPE)
  200. add_library(${target_name} INTERFACE IMPORTED)
  201. if(NOT EXISTS ${file_with_block})
  202. message(FATAL_ERROR "Unable to find file ${file_with_block}")
  203. endif()
  204. file(STRINGS ${file_with_block} module_header_contents)
  205. set(last_written_key)
  206. set(append NO)
  207. foreach(line IN LISTS module_header_contents)
  208. if(NOT append)
  209. if(line MATCHES " *BEGIN_${delim_str} *")
  210. set(append YES)
  211. endif()
  212. continue()
  213. endif()
  214. if(append AND (line MATCHES " *END_${delim_str} *"))
  215. break()
  216. endif()
  217. if(line MATCHES "^ *([a-zA-Z]+):")
  218. set(last_written_key "${CMAKE_MATCH_1}")
  219. endif()
  220. string(REGEX REPLACE "^ *${last_written_key}: *" "" line "${line}")
  221. string(REGEX REPLACE "[ ,]+" ";" line "${line}")
  222. set_property(TARGET ${target_name} APPEND PROPERTY
  223. "INTERFACE_JUCE_${last_written_key}" "${line}")
  224. endforeach()
  225. endfunction()
  226. # Fetches properties attached to a metadata target.
  227. function(_juce_get_metadata target key out_var)
  228. get_target_property(content "${target}" "INTERFACE_JUCE_${key}")
  229. if(NOT "${content}" STREQUAL "content-NOTFOUND")
  230. set(${out_var} "${content}" PARENT_SCOPE)
  231. endif()
  232. endfunction()
  233. # ==================================================================================================
  234. function(_juce_should_build_module_source filename output_var)
  235. get_filename_component(trimmed_name "${filename}" NAME_WE)
  236. set(result TRUE)
  237. set(pairs
  238. "OSX\;Darwin"
  239. "Windows\;Windows"
  240. "Linux\;Linux"
  241. "Android\;Android"
  242. "iOS\;iOS")
  243. foreach(pair IN LISTS pairs)
  244. list(GET pair 0 suffix)
  245. list(GET pair 1 system_name)
  246. if((trimmed_name MATCHES "_${suffix}$") AND NOT (CMAKE_SYSTEM_NAME STREQUAL "${system_name}"))
  247. set(result FALSE)
  248. endif()
  249. endforeach()
  250. set("${output_var}" "${result}" PARENT_SCOPE)
  251. endfunction()
  252. function(_juce_module_sources module_path output_path built_sources other_sources)
  253. get_filename_component(module_parent_path ${module_path} DIRECTORY)
  254. get_filename_component(module_glob ${module_path} NAME)
  255. file(GLOB_RECURSE all_module_files
  256. CONFIGURE_DEPENDS LIST_DIRECTORIES FALSE
  257. RELATIVE "${module_parent_path}"
  258. "${module_path}/*")
  259. set(base_path "${module_glob}/${module_glob}")
  260. set(module_cpp ${all_module_files})
  261. list(FILTER module_cpp INCLUDE REGEX "^${base_path}[^/]*\\.(c|cc|cpp|cxx|s|asm)$")
  262. if(APPLE)
  263. set(module_mm ${all_module_files})
  264. list(FILTER module_mm INCLUDE REGEX "^${base_path}[^/]*\\.mm$")
  265. if(module_mm)
  266. set(module_mm_replaced ${module_mm})
  267. list(TRANSFORM module_mm_replaced REPLACE "\\.mm$" ".cpp")
  268. list(REMOVE_ITEM module_cpp ${module_mm_replaced})
  269. endif()
  270. set(module_apple_files ${all_module_files})
  271. list(FILTER module_apple_files INCLUDE REGEX "${base_path}[^/]*\\.(m|mm|metal|r|swift)$")
  272. list(APPEND module_cpp ${module_apple_files})
  273. endif()
  274. set(headers ${all_module_files})
  275. set(module_files_to_build)
  276. foreach(filename IN LISTS module_cpp)
  277. _juce_should_build_module_source("${filename}" should_build_file)
  278. if(should_build_file)
  279. list(APPEND module_files_to_build "${filename}")
  280. endif()
  281. endforeach()
  282. if(NOT "${module_files_to_build}" STREQUAL "")
  283. list(REMOVE_ITEM headers ${module_files_to_build})
  284. endif()
  285. foreach(source_list IN ITEMS module_files_to_build headers)
  286. list(TRANSFORM ${source_list} PREPEND "${output_path}/")
  287. endforeach()
  288. set(${built_sources} ${module_files_to_build} PARENT_SCOPE)
  289. set(${other_sources} ${headers} PARENT_SCOPE)
  290. endfunction()
  291. # ==================================================================================================
  292. function(_juce_get_all_plugin_kinds out)
  293. set(${out} AU AUv3 AAX Standalone Unity VST VST3 PARENT_SCOPE)
  294. endfunction()
  295. function(_juce_get_platform_plugin_kinds out)
  296. set(result Standalone)
  297. if(APPLE AND (CMAKE_GENERATOR STREQUAL "Xcode"))
  298. list(APPEND result AUv3)
  299. endif()
  300. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  301. list(APPEND result AU)
  302. endif()
  303. if(NOT CMAKE_SYSTEM_NAME STREQUAL "iOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
  304. list(APPEND result AAX Unity VST VST3)
  305. endif()
  306. set(${out} ${result} PARENT_SCOPE)
  307. endfunction()
  308. function(_juce_add_plugin_definitions target visibility)
  309. _juce_get_all_plugin_kinds(options)
  310. cmake_parse_arguments(JUCE_ARG "${options}" "" "" ${ARGN})
  311. foreach(opt IN LISTS options)
  312. set(flag_value 0)
  313. if(JUCE_ARG_${opt})
  314. set(flag_value 1)
  315. endif()
  316. target_compile_definitions(${target} ${visibility} "JucePlugin_Build_${opt}=${flag_value}")
  317. endforeach()
  318. endfunction()
  319. # ==================================================================================================
  320. function(_juce_add_au_resource_fork shared_code_target au_target)
  321. if(NOT JUCE_XCRUN)
  322. return()
  323. endif()
  324. get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME)
  325. get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES)
  326. list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$")
  327. if(NOT module_sources)
  328. message(FATAL_ERROR "Failed to find AU resource file input")
  329. endif()
  330. list(GET module_sources 0 au_rez_sources)
  331. get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  332. # We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it
  333. set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret")
  334. set(secret_au_plugindefines "${secret_au_resource_dir}/JucePluginDefines.h")
  335. set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc")
  336. target_sources(${au_target} PRIVATE "${au_rez_output}")
  337. set_source_files_properties("${au_rez_output}" PROPERTIES
  338. GENERATED TRUE
  339. MACOSX_PACKAGE_LOCATION Resources)
  340. set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},JUCE_DEFS_FILE>>)
  341. # Passing all our compile definitions using generator expressions is really painful
  342. # because some of the definitions have pipes and quotes and dollars and goodness-knows
  343. # what else that the shell would very much like to claim for itself, thank you very much.
  344. # CMake definitely knows how to escape all these things, because it's perfectly happy to pass
  345. # them to compiler invocations, but I have no idea how to get it to escape them
  346. # in a custom command.
  347. # In the end, it's simplest to generate a special single-purpose appconfig just for the
  348. # resource compiler.
  349. add_custom_command(OUTPUT "${secret_au_plugindefines}"
  350. COMMAND juce::juceaide auplugindefines "${defs_file}" "${secret_au_plugindefines}"
  351. DEPENDS "${defs_file}"
  352. VERBATIM)
  353. add_custom_command(OUTPUT "${au_rez_output}"
  354. COMMAND "${JUCE_XCRUN}" Rez
  355. -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64"
  356. -I "${secret_au_resource_dir}"
  357. -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers"
  358. -I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers"
  359. -isysroot "${CMAKE_OSX_SYSROOT}"
  360. "${au_rez_sources}"
  361. -useDF
  362. -o "${au_rez_output}"
  363. DEPENDS "${secret_au_plugindefines}"
  364. VERBATIM)
  365. set(au_resource_directory "$<TARGET_BUNDLE_DIR:${au_target}>/Contents/Resources")
  366. endfunction()
  367. # ==================================================================================================
  368. # Takes a target, a link visibility, and a variable-length list of framework
  369. # names. On macOS, finds the requested frameworks using `find_library` and
  370. # links them. On iOS, links directly with `-framework Name`.
  371. function(_juce_link_frameworks target visibility)
  372. foreach(framework IN LISTS ARGN)
  373. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  374. find_library("juce_found_${framework}" "${framework}" REQUIRED)
  375. target_link_libraries("${target}" "${visibility}" "${juce_found_${framework}}")
  376. elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  377. # CoreServices is only available on iOS 12+, we must link it weakly on earlier platforms
  378. if((framework STREQUAL "CoreServices") AND (CMAKE_OSX_DEPLOYMENT_TARGET LESS 12.0))
  379. set(framework_flags "-weak_framework ${framework}")
  380. else()
  381. set(framework_flags "-framework ${framework}")
  382. endif()
  383. target_link_libraries("${target}" "${visibility}" "${framework_flags}")
  384. endif()
  385. endforeach()
  386. endfunction()
  387. # ==================================================================================================
  388. function(_juce_add_plugin_wrapper_target format path out_path)
  389. _juce_module_sources("${path}" "${out_path}" out_var headers)
  390. list(FILTER out_var EXCLUDE REGEX "/juce_audio_plugin_client_utils.cpp$")
  391. set(target_name juce_audio_plugin_client_${format})
  392. _juce_add_interface_library("${target_name}" ${out_var})
  393. _juce_add_plugin_definitions("${target_name}" INTERFACE ${format})
  394. _juce_add_standard_defs("${target_name}")
  395. target_compile_features("${target_name}" INTERFACE cxx_std_11)
  396. add_library("juce::${target_name}" ALIAS "${target_name}")
  397. if(format STREQUAL "AUv3")
  398. _juce_link_frameworks("${target_name}" INTERFACE AVFoundation)
  399. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  400. _juce_link_frameworks("${target_name}" INTERFACE AudioUnit)
  401. endif()
  402. elseif(format STREQUAL "AU")
  403. _juce_link_frameworks("${target_name}" INTERFACE AudioUnit CoreAudioKit)
  404. endif()
  405. endfunction()
  406. # ==================================================================================================
  407. function(_juce_link_libs_from_metadata module_name dict key)
  408. _juce_get_metadata("${dict}" "${key}" libs)
  409. if(libs)
  410. target_link_libraries(${module_name} INTERFACE ${libs})
  411. endif()
  412. endfunction()
  413. # ==================================================================================================
  414. function(juce_add_module module_path)
  415. set(one_value_args INSTALL_PATH ALIAS_NAMESPACE)
  416. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN})
  417. _juce_make_absolute(module_path)
  418. get_filename_component(module_name ${module_path} NAME)
  419. get_filename_component(module_parent_path ${module_path} DIRECTORY)
  420. set(module_header_name "${module_name}.h")
  421. if(NOT EXISTS "${module_path}/${module_header_name}")
  422. set(module_header_name "${module_header_name}pp")
  423. endif()
  424. if(NOT EXISTS "${module_path}/${module_header_name}")
  425. message(FATAL_ERROR "Could not locate module header for module '${module_path}'")
  426. endif()
  427. set(base_path "${module_parent_path}")
  428. _juce_module_sources("${module_path}" "${base_path}" globbed_sources headers)
  429. if(${module_name} STREQUAL "juce_audio_plugin_client")
  430. _juce_get_platform_plugin_kinds(plugin_kinds)
  431. foreach(kind IN LISTS plugin_kinds)
  432. _juce_add_plugin_wrapper_target(${kind} "${module_path}" "${base_path}")
  433. endforeach()
  434. set(utils_source
  435. "${base_path}/${module_name}/juce_audio_plugin_client_utils.cpp")
  436. add_library(juce_audio_plugin_client_utils INTERFACE)
  437. target_sources(juce_audio_plugin_client_utils INTERFACE "${utils_source}")
  438. if(JUCE_ARG_ALIAS_NAMESPACE)
  439. add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_audio_plugin_client_utils
  440. ALIAS juce_audio_plugin_client_utils)
  441. endif()
  442. file(GLOB_RECURSE all_module_files
  443. CONFIGURE_DEPENDS LIST_DIRECTORIES FALSE
  444. RELATIVE "${module_parent_path}"
  445. "${module_path}/*")
  446. else()
  447. list(APPEND all_module_sources ${globbed_sources})
  448. endif()
  449. _juce_add_interface_library(${module_name} ${all_module_sources})
  450. set_property(GLOBAL APPEND PROPERTY _juce_module_names ${module_name})
  451. set_target_properties(${module_name} PROPERTIES
  452. INTERFACE_JUCE_MODULE_SOURCES "${globbed_sources}"
  453. INTERFACE_JUCE_MODULE_HEADERS "${headers}"
  454. INTERFACE_JUCE_MODULE_PATH "${base_path}")
  455. if(JUCE_ENABLE_MODULE_SOURCE_GROUPS)
  456. target_sources(${module_name} INTERFACE ${headers})
  457. endif()
  458. if(${module_name} STREQUAL "juce_core")
  459. _juce_add_standard_defs(${module_name})
  460. target_link_libraries(juce_core INTERFACE juce::juce_atomic_wrapper)
  461. if(CMAKE_SYSTEM_NAME MATCHES ".*BSD")
  462. target_link_libraries(juce_core INTERFACE execinfo)
  463. elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
  464. target_sources(juce_core INTERFACE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
  465. target_include_directories(juce_core INTERFACE "${ANDROID_NDK}/sources/android/cpufeatures")
  466. target_link_libraries(juce_core INTERFACE android log)
  467. endif()
  468. endif()
  469. if(${module_name} STREQUAL "juce_audio_processors")
  470. add_library(juce_vst3_headers INTERFACE)
  471. target_compile_definitions(juce_vst3_headers INTERFACE "$<$<TARGET_EXISTS:juce_vst3_sdk>:JUCE_CUSTOM_VST3_SDK=1>")
  472. target_include_directories(juce_vst3_headers INTERFACE
  473. "$<$<TARGET_EXISTS:juce_vst3_sdk>:$<TARGET_PROPERTY:juce_vst3_sdk,INTERFACE_INCLUDE_DIRECTORIES>>"
  474. "$<$<NOT:$<TARGET_EXISTS:juce_vst3_sdk>>:${base_path}/juce_audio_processors/format_types/VST3_SDK>")
  475. target_link_libraries(juce_audio_processors INTERFACE juce_vst3_headers)
  476. if(JUCE_ARG_ALIAS_NAMESPACE)
  477. add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_vst3_headers ALIAS juce_vst3_headers)
  478. endif()
  479. endif()
  480. target_include_directories(${module_name} INTERFACE ${base_path})
  481. target_compile_definitions(${module_name} INTERFACE JUCE_MODULE_AVAILABLE_${module_name}=1)
  482. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  483. target_compile_definitions(${module_name} INTERFACE LINUX=1)
  484. endif()
  485. _juce_extract_metadata_block(JUCE_MODULE_DECLARATION "${module_path}/${module_header_name}" metadata_dict)
  486. _juce_get_metadata("${metadata_dict}" minimumCppStandard module_cpp_standard)
  487. if(module_cpp_standard)
  488. target_compile_features(${module_name} INTERFACE cxx_std_${module_cpp_standard})
  489. else()
  490. target_compile_features(${module_name} INTERFACE cxx_std_11)
  491. endif()
  492. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  493. _juce_get_metadata("${metadata_dict}" OSXFrameworks module_osxframeworks)
  494. foreach(module_framework IN LISTS module_osxframeworks)
  495. if(module_framework STREQUAL "")
  496. continue()
  497. endif()
  498. _juce_link_frameworks("${module_name}" INTERFACE "${module_framework}")
  499. endforeach()
  500. _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" OSXLibs)
  501. elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  502. _juce_get_metadata("${metadata_dict}" iOSFrameworks module_iosframeworks)
  503. foreach(module_framework IN LISTS module_iosframeworks)
  504. if(module_framework STREQUAL "")
  505. continue()
  506. endif()
  507. _juce_link_frameworks("${module_name}" INTERFACE "${module_framework}")
  508. endforeach()
  509. _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" iOSLibs)
  510. elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  511. _juce_get_metadata("${metadata_dict}" linuxPackages module_linuxpackages)
  512. if(module_linuxpackages)
  513. _juce_create_pkgconfig_target(${module_name}_LINUX_DEPS ${module_linuxpackages})
  514. target_link_libraries(${module_name} INTERFACE juce::pkgconfig_${module_name}_LINUX_DEPS)
  515. endif()
  516. _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" linuxLibs)
  517. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  518. if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") OR (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
  519. if(module_name STREQUAL "juce_gui_basics")
  520. target_compile_options(${module_name} INTERFACE /bigobj)
  521. endif()
  522. _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" windowsLibs)
  523. elseif(MSYS OR MINGW)
  524. if(module_name STREQUAL "juce_gui_basics")
  525. target_compile_options(${module_name} INTERFACE "-Wa,-mbig-obj")
  526. endif()
  527. _juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" mingwLibs)
  528. endif()
  529. endif()
  530. _juce_get_metadata("${metadata_dict}" dependencies module_dependencies)
  531. target_link_libraries(${module_name} INTERFACE ${module_dependencies})
  532. _juce_get_metadata("${metadata_dict}" searchpaths module_searchpaths)
  533. if(NOT module_searchpaths STREQUAL "")
  534. foreach(module_searchpath IN LISTS module_searchpaths)
  535. target_include_directories(${module_name}
  536. INTERFACE "${module_path}/${module_searchpath}")
  537. endforeach()
  538. endif()
  539. if(JUCE_ARG_INSTALL_PATH)
  540. install(DIRECTORY "${module_path}" DESTINATION "${JUCE_ARG_INSTALL_PATH}")
  541. endif()
  542. if(JUCE_ARG_ALIAS_NAMESPACE)
  543. add_library(${JUCE_ARG_ALIAS_NAMESPACE}::${module_name} ALIAS ${module_name})
  544. endif()
  545. endfunction()
  546. function(juce_add_modules)
  547. set(one_value_args INSTALL_PATH ALIAS_NAMESPACE)
  548. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN})
  549. foreach(path IN LISTS JUCE_ARG_UNPARSED_ARGUMENTS)
  550. juce_add_module(${path}
  551. INSTALL_PATH "${JUCE_ARG_INSTALL_PATH}"
  552. ALIAS_NAMESPACE "${JUCE_ARG_ALIAS_NAMESPACE}")
  553. endforeach()
  554. endfunction()
  555. # ==================================================================================================
  556. # Ideally, we'd check the preprocessor defs on the target to see whether
  557. # JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off,
  558. # and then link libraries as appropriate.
  559. # Unfortunately, this doesn't work, because linking a new library (curl/webkit/StoreKit)
  560. # updates the target's compile defs, which results in a recursion/circular-dependency.
  561. # Instead, we ask the user to explicitly request curl/webkit/StoreKit linking if they
  562. # know they need it. Otherwise, we won't link anything.
  563. # See the NEEDS_CURL, NEEDS_WEB_BROWSER, and NEEDS_STORE_KIT options in the CMake/readme.md.
  564. function(_juce_link_optional_libraries target)
  565. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  566. get_target_property(needs_curl ${target} JUCE_NEEDS_CURL)
  567. if(needs_curl)
  568. target_link_libraries(${target} PRIVATE juce::pkgconfig_JUCE_CURL_LINUX_DEPS)
  569. endif()
  570. get_target_property(needs_browser ${target} JUCE_NEEDS_WEB_BROWSER)
  571. if(needs_browser)
  572. target_link_libraries(${target} PRIVATE juce::pkgconfig_JUCE_BROWSER_LINUX_DEPS)
  573. endif()
  574. elseif(APPLE)
  575. get_target_property(needs_storekit ${target} JUCE_NEEDS_STORE_KIT)
  576. if(needs_storekit)
  577. _juce_link_frameworks("${target}" PRIVATE StoreKit)
  578. endif()
  579. get_target_property(needs_camera ${target} JUCE_CAMERA_PERMISSION_ENABLED)
  580. if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND needs_camera)
  581. _juce_link_frameworks("${target}" PRIVATE ImageIO)
  582. endif()
  583. endif()
  584. endfunction()
  585. # ==================================================================================================
  586. function(_juce_get_module_definitions target filter out_var)
  587. set(compile_defs $<TARGET_GENEX_EVAL:${target},$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>>)
  588. if(filter)
  589. set(${out_var} $<FILTER:${compile_defs},EXCLUDE,JucePlugin_Build_|JUCE_SHARED_CODE> PARENT_SCOPE)
  590. else()
  591. set(${out_var} ${compile_defs} PARENT_SCOPE)
  592. endif()
  593. endfunction()
  594. function(_juce_append_record output key)
  595. string(ASCII 30 RS)
  596. string(ASCII 31 US)
  597. set(${output} "${${output}}${key}${US}${ARGN}${RS}" PARENT_SCOPE)
  598. endfunction()
  599. function(_juce_append_target_property output key target property)
  600. get_target_property(prop ${target} ${property})
  601. if(prop STREQUAL "prop-NOTFOUND")
  602. set(prop)
  603. endif()
  604. _juce_append_record(${output} ${key} ${prop})
  605. set(${output} "${${output}}" PARENT_SCOPE)
  606. endfunction()
  607. # This is all info that should be known at configure time (i.e. no generator expressions here!)
  608. # We use this info to generate plists and entitlements files, also at configure time.
  609. function(_juce_write_configure_time_info target)
  610. _juce_append_target_property(file_content EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME)
  611. _juce_append_target_property(file_content VERSION ${target} JUCE_VERSION)
  612. _juce_append_target_property(file_content BUILD_VERSION ${target} JUCE_BUILD_VERSION)
  613. _juce_append_target_property(file_content PLIST_TO_MERGE ${target} JUCE_PLIST_TO_MERGE)
  614. _juce_append_target_property(file_content BUNDLE_ID ${target} JUCE_BUNDLE_ID)
  615. _juce_append_target_property(file_content XCODE_EXTRA_PLIST_ENTRIES ${target} JUCE_XCODE_EXTRA_PLIST_ENTRIES)
  616. _juce_append_target_property(file_content MICROPHONE_PERMISSION_ENABLED ${target} JUCE_MICROPHONE_PERMISSION_ENABLED)
  617. _juce_append_target_property(file_content MICROPHONE_PERMISSION_TEXT ${target} JUCE_MICROPHONE_PERMISSION_TEXT)
  618. _juce_append_target_property(file_content CAMERA_PERMISSION_ENABLED ${target} JUCE_CAMERA_PERMISSION_ENABLED)
  619. _juce_append_target_property(file_content CAMERA_PERMISSION_TEXT ${target} JUCE_CAMERA_PERMISSION_TEXT)
  620. _juce_append_target_property(file_content BLUETOOTH_PERMISSION_ENABLED ${target} JUCE_BLUETOOTH_PERMISSION_ENABLED)
  621. _juce_append_target_property(file_content BLUETOOTH_PERMISSION_TEXT ${target} JUCE_BLUETOOTH_PERMISSION_TEXT)
  622. _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_ENABLED ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_ENABLED)
  623. _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_TEXT ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_TEXT)
  624. _juce_append_target_property(file_content SHOULD_ADD_STORYBOARD ${target} JUCE_SHOULD_ADD_STORYBOARD)
  625. _juce_append_target_property(file_content LAUNCH_STORYBOARD_FILE ${target} JUCE_LAUNCH_STORYBOARD_FILE)
  626. _juce_append_target_property(file_content ICON_FILE ${target} JUCE_ICON_FILE)
  627. _juce_append_target_property(file_content PROJECT_NAME ${target} JUCE_PRODUCT_NAME)
  628. _juce_append_target_property(file_content COMPANY_COPYRIGHT ${target} JUCE_COMPANY_COPYRIGHT)
  629. _juce_append_target_property(file_content COMPANY_NAME ${target} JUCE_COMPANY_NAME)
  630. _juce_append_target_property(file_content DOCUMENT_EXTENSIONS ${target} JUCE_DOCUMENT_EXTENSIONS)
  631. _juce_append_target_property(file_content FILE_SHARING_ENABLED ${target} JUCE_FILE_SHARING_ENABLED)
  632. _juce_append_target_property(file_content DOCUMENT_BROWSER_ENABLED ${target} JUCE_DOCUMENT_BROWSER_ENABLED)
  633. _juce_append_target_property(file_content STATUS_BAR_HIDDEN ${target} JUCE_STATUS_BAR_HIDDEN)
  634. _juce_append_target_property(file_content REQUIRES_FULL_SCREEN ${target} JUCE_REQUIRES_FULL_SCREEN)
  635. _juce_append_target_property(file_content BACKGROUND_AUDIO_ENABLED ${target} JUCE_BACKGROUND_AUDIO_ENABLED)
  636. _juce_append_target_property(file_content BACKGROUND_BLE_ENABLED ${target} JUCE_BACKGROUND_BLE_ENABLED)
  637. _juce_append_target_property(file_content PUSH_NOTIFICATIONS_ENABLED ${target} JUCE_PUSH_NOTIFICATIONS_ENABLED)
  638. _juce_append_target_property(file_content PLUGIN_MANUFACTURER_CODE ${target} JUCE_PLUGIN_MANUFACTURER_CODE)
  639. _juce_append_target_property(file_content PLUGIN_CODE ${target} JUCE_PLUGIN_CODE)
  640. _juce_append_target_property(file_content IPHONE_SCREEN_ORIENTATIONS ${target} JUCE_IPHONE_SCREEN_ORIENTATIONS)
  641. _juce_append_target_property(file_content IPAD_SCREEN_ORIENTATIONS ${target} JUCE_IPAD_SCREEN_ORIENTATIONS)
  642. _juce_append_target_property(file_content PLUGIN_NAME ${target} JUCE_PLUGIN_NAME)
  643. _juce_append_target_property(file_content PLUGIN_MANUFACTURER ${target} JUCE_COMPANY_NAME)
  644. _juce_append_target_property(file_content PLUGIN_DESCRIPTION ${target} JUCE_DESCRIPTION)
  645. _juce_append_target_property(file_content PLUGIN_AU_EXPORT_PREFIX ${target} JUCE_AU_EXPORT_PREFIX)
  646. _juce_append_target_property(file_content PLUGIN_AU_MAIN_TYPE ${target} JUCE_AU_MAIN_TYPE_CODE)
  647. _juce_append_target_property(file_content IS_AU_SANDBOX_SAFE ${target} JUCE_AU_SANDBOX_SAFE)
  648. _juce_append_target_property(file_content IS_PLUGIN_SYNTH ${target} JUCE_IS_SYNTH)
  649. _juce_append_target_property(file_content SUPPRESS_AU_PLIST_RESOURCE_USAGE ${target} JUCE_SUPPRESS_AU_PLIST_RESOURCE_USAGE)
  650. _juce_append_target_property(file_content HARDENED_RUNTIME_ENABLED ${target} JUCE_HARDENED_RUNTIME_ENABLED)
  651. _juce_append_target_property(file_content APP_SANDBOX_ENABLED ${target} JUCE_APP_SANDBOX_ENABLED)
  652. _juce_append_target_property(file_content APP_SANDBOX_INHERIT ${target} JUCE_APP_SANDBOX_INHERIT)
  653. _juce_append_target_property(file_content HARDENED_RUNTIME_OPTIONS ${target} JUCE_HARDENED_RUNTIME_OPTIONS)
  654. _juce_append_target_property(file_content APP_SANDBOX_OPTIONS ${target} JUCE_APP_SANDBOX_OPTIONS)
  655. _juce_append_target_property(file_content APP_GROUPS_ENABLED ${target} JUCE_APP_GROUPS_ENABLED)
  656. _juce_append_target_property(file_content APP_GROUP_IDS ${target} JUCE_APP_GROUP_IDS)
  657. _juce_append_target_property(file_content IS_PLUGIN ${target} JUCE_IS_PLUGIN)
  658. _juce_append_target_property(file_content ICLOUD_PERMISSIONS_ENABLED ${target} JUCE_ICLOUD_PERMISSIONS_ENABLED)
  659. if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  660. _juce_append_record(file_content IS_IOS 1)
  661. else()
  662. _juce_append_record(file_content IS_IOS 0)
  663. endif()
  664. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  665. set(info_file "${juce_library_code}/Info.txt")
  666. file(WRITE "${info_file}" "${file_content}")
  667. set_target_properties(${target} PROPERTIES JUCE_INFO_FILE "${info_file}")
  668. endfunction()
  669. # In this file, we put things that CMake is only able to divine at generate time, like preprocessor definitions.
  670. # We use the target preprocessor definitions to work out which JUCE modules should go in the JuceHeader.h.
  671. function(_juce_write_generate_time_info target)
  672. _juce_get_module_definitions(${target} OFF module_defs)
  673. _juce_append_record(defs MODULE_DEFINITIONS ${module_defs})
  674. _juce_append_target_property(defs EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME)
  675. _juce_append_target_property(defs PROJECT_NAME ${target} JUCE_PRODUCT_NAME)
  676. _juce_append_target_property(defs VERSION ${target} JUCE_VERSION)
  677. _juce_append_target_property(defs COMPANY_NAME ${target} JUCE_COMPANY_NAME)
  678. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  679. set(defs_file "${juce_library_code}/$<CONFIG>/Defs.txt")
  680. file(GENERATE OUTPUT "${defs_file}" CONTENT "${defs}")
  681. set_target_properties(${target} PROPERTIES JUCE_DEFS_FILE "${defs_file}")
  682. endfunction()
  683. # ==================================================================================================
  684. function(juce_add_binary_data target)
  685. set(one_value_args NAMESPACE HEADER_NAME)
  686. set(multi_value_args SOURCES)
  687. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
  688. list(LENGTH JUCE_ARG_SOURCES num_binary_files)
  689. if(${num_binary_files} LESS 1)
  690. message(FATAL_ERROR "juce_add_binary_data must be passed at least one file to encode")
  691. endif()
  692. add_library(${target} STATIC)
  693. set(juce_binary_data_folder "${CMAKE_CURRENT_BINARY_DIR}/juce_binarydata_${target}/JuceLibraryCode")
  694. set(binary_file_names)
  695. foreach(index RANGE 1 ${num_binary_files})
  696. list(APPEND binary_file_names "${juce_binary_data_folder}/BinaryData${index}.cpp")
  697. endforeach()
  698. file(MAKE_DIRECTORY ${juce_binary_data_folder})
  699. if(NOT JUCE_ARG_NAMESPACE)
  700. set(JUCE_ARG_NAMESPACE BinaryData)
  701. endif()
  702. if(NOT JUCE_ARG_HEADER_NAME)
  703. set(JUCE_ARG_HEADER_NAME BinaryData.h)
  704. endif()
  705. list(APPEND binary_file_names "${juce_binary_data_folder}/${JUCE_ARG_HEADER_NAME}")
  706. set(newline_delimited_input)
  707. foreach(name IN LISTS JUCE_ARG_SOURCES)
  708. _juce_make_absolute_and_check(name)
  709. set(newline_delimited_input "${newline_delimited_input}${name}\n")
  710. endforeach()
  711. set(input_file_list "${juce_binary_data_folder}/input_file_list")
  712. file(WRITE "${input_file_list}" "${newline_delimited_input}")
  713. add_custom_command(OUTPUT ${binary_file_names}
  714. COMMAND juce::juceaide binarydata "${JUCE_ARG_NAMESPACE}" "${JUCE_ARG_HEADER_NAME}"
  715. ${juce_binary_data_folder} "${input_file_list}"
  716. WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  717. DEPENDS "${input_file_list}"
  718. VERBATIM)
  719. target_sources(${target} PRIVATE "${binary_file_names}")
  720. target_include_directories(${target} INTERFACE ${juce_binary_data_folder})
  721. target_compile_features(${target} PRIVATE cxx_std_11)
  722. # This fixes an issue where Xcode is unable to find binary data during archive.
  723. if(CMAKE_GENERATOR STREQUAL "Xcode")
  724. set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "./")
  725. endif()
  726. if(JUCE_ARG_HEADER_NAME STREQUAL "BinaryData.h")
  727. target_compile_definitions(${target} INTERFACE JUCE_TARGET_HAS_BINARY_DATA=1)
  728. endif()
  729. endfunction()
  730. # ==================================================================================================
  731. # math(EXPR ... OUTPUT_FORMAT HEXADECIMAL) wasn't added until 3.13, but we need 3.12 for vcpkg
  732. # compatibility
  733. function(_juce_dec_to_hex num out_var)
  734. while(num)
  735. math(EXPR digit "${num} % 16")
  736. math(EXPR num "${num} / 16")
  737. if(digit GREATER_EQUAL 10)
  738. math(EXPR ascii_code "${digit} + 55")
  739. string(ASCII "${ascii_code}" digit)
  740. endif()
  741. set(result "${digit}${result}")
  742. endwhile()
  743. set(${out_var} "${result}" PARENT_SCOPE)
  744. endfunction()
  745. function(_juce_version_code version_in out_var)
  746. string(REGEX REPLACE "\\." ";" version_list ${version_in})
  747. list(LENGTH version_list num_version_components)
  748. set(version_major 0)
  749. set(version_minor 0)
  750. set(version_patch 0)
  751. if(num_version_components GREATER 0)
  752. list(GET version_list 0 version_major)
  753. endif()
  754. if(num_version_components GREATER 1)
  755. list(GET version_list 1 version_minor)
  756. endif()
  757. if(num_version_components GREATER 2)
  758. list(GET version_list 2 version_patch)
  759. endif()
  760. math(EXPR decimal "(${version_major} << 16) + (${version_minor} << 8) + ${version_patch}")
  761. _juce_dec_to_hex(${decimal} hex)
  762. set(${out_var} "${hex}" PARENT_SCOPE)
  763. endfunction()
  764. function(_juce_to_char_literal str out_var)
  765. string(APPEND str " ") # Make sure there are at least 4 characters in the string.
  766. # Round-tripping through a file is the simplest way to convert a string to hex...
  767. string(SUBSTRING "${str}" 0 4 four_chars)
  768. string(RANDOM LENGTH 16 random_string)
  769. set(scratch_file "${CMAKE_CURRENT_BINARY_DIR}/${random_string}_ascii_conversion.txt")
  770. file(WRITE "${scratch_file}" "${four_chars}")
  771. file(READ "${scratch_file}" four_chars_hex HEX)
  772. file(REMOVE "${scratch_file}")
  773. set(${out_var} ${four_chars_hex} PARENT_SCOPE)
  774. endfunction()
  775. # ==================================================================================================
  776. function(juce_generate_juce_header target)
  777. get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY)
  778. if(NOT juce_library_code)
  779. message(FATAL_ERROR "Target ${target} does not have a generated sources directory. Ensure it was created with a juce_add_* function")
  780. endif()
  781. set(juce_header ${juce_library_code}/JuceHeader.h)
  782. target_sources(${target} PRIVATE ${juce_header})
  783. set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${target},JUCE_DEFS_FILE>>)
  784. set(extra_args)
  785. add_custom_command(OUTPUT "${juce_header}"
  786. COMMAND juce::juceaide header "${defs_file}" "${juce_header}" ${extra_args}
  787. DEPENDS "${defs_file}"
  788. VERBATIM)
  789. endfunction()
  790. # ==================================================================================================
  791. function(_juce_execute_juceaide)
  792. if(NOT TARGET juce::juceaide)
  793. message(FATAL_ERROR "The juceaide target does not exist")
  794. endif()
  795. get_target_property(juceaide_location juce::juceaide IMPORTED_LOCATION)
  796. if(NOT EXISTS "${juceaide_location}")
  797. message(FATAL_ERROR "juceaide was imported, but it doesn't exist!")
  798. endif()
  799. execute_process(COMMAND "${juceaide_location}" ${ARGN} RESULT_VARIABLE result_variable)
  800. if(result_variable)
  801. message(FATAL_ERROR "Running juceaide failed")
  802. endif()
  803. endfunction()
  804. function(_juce_set_output_name target name)
  805. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
  806. set_target_properties(${target} PROPERTIES
  807. OUTPUT_NAME ${name}
  808. XCODE_ATTRIBUTE_PRODUCT_NAME ${name})
  809. endif()
  810. endfunction()
  811. function(_juce_check_icon_files_exist icon_files)
  812. foreach(file IN LISTS icon_files)
  813. if(NOT EXISTS "${file}")
  814. message(FATAL_ERROR "Could not find icon file: ${file}")
  815. endif()
  816. endforeach()
  817. endfunction()
  818. function(_juce_generate_icon source_target dest_target)
  819. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  820. get_target_property(juce_property_icon_big ${source_target} JUCE_ICON_BIG)
  821. get_target_property(juce_property_icon_small ${source_target} JUCE_ICON_SMALL)
  822. set(icon_args)
  823. if(juce_property_icon_big)
  824. list(APPEND icon_args "${juce_property_icon_big}")
  825. endif()
  826. if(juce_property_icon_small)
  827. list(APPEND icon_args "${juce_property_icon_small}")
  828. endif()
  829. set(generated_icon)
  830. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  831. if(NOT icon_args)
  832. return()
  833. endif()
  834. _juce_check_icon_files_exist("${icon_args}")
  835. set(generated_icon "${juce_library_code}/Icon.icns")
  836. # To get compiled properly, we need the icon before the plist is generated!
  837. _juce_execute_juceaide(macicon "${generated_icon}" ${icon_args})
  838. set_source_files_properties(${generated_icon} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
  839. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  840. if(NOT icon_args)
  841. return()
  842. endif()
  843. _juce_check_icon_files_exist("${icon_args}")
  844. set(generated_icon "${juce_library_code}/icon.ico")
  845. _juce_execute_juceaide(winicon "${generated_icon}" ${icon_args})
  846. elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  847. get_target_property(generated_icon ${source_target} JUCE_CUSTOM_XCASSETS_FOLDER)
  848. if(icon_args AND (NOT generated_icon))
  849. _juce_check_icon_files_exist("${icon_args}")
  850. set(out_path "${juce_library_code}/${dest_target}")
  851. set(generated_icon "${out_path}/Images.xcassets")
  852. # To get compiled properly, we need iOS assets at configure time!
  853. _juce_execute_juceaide(iosassets "${out_path}" ${icon_args})
  854. endif()
  855. if(NOT generated_icon)
  856. return()
  857. endif()
  858. set_target_properties(${dest_target} PROPERTIES
  859. XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon")
  860. get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD)
  861. if(NOT add_storyboard)
  862. set_target_properties(${dest_target} PROPERTIES
  863. XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME "LaunchImage")
  864. endif()
  865. endif()
  866. if(generated_icon)
  867. _juce_check_icon_files_exist("${generated_icon}")
  868. target_sources(${dest_target} PRIVATE ${generated_icon})
  869. set_target_properties(${source_target} ${dest_target} PROPERTIES
  870. JUCE_ICON_FILE "${generated_icon}"
  871. RESOURCE "${generated_icon}")
  872. endif()
  873. endfunction()
  874. function(_juce_add_xcode_entitlements source_target dest_target)
  875. get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING)
  876. get_target_property(input_info_file ${source_target} JUCE_INFO_FILE)
  877. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  878. set(entitlements_file "${juce_library_code}/${dest_target}.entitlements")
  879. _juce_execute_juceaide(entitlements "${juce_kind_string}" "${input_info_file}" "${entitlements_file}")
  880. set_target_properties(${dest_target} PROPERTIES
  881. XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${entitlements_file}")
  882. endfunction()
  883. function(_juce_configure_bundle source_target dest_target)
  884. _juce_generate_icon(${source_target} ${dest_target})
  885. _juce_write_configure_time_info(${source_target})
  886. if(NOT APPLE)
  887. return()
  888. endif()
  889. get_target_property(generated_icon ${source_target} JUCE_ICON_FILE)
  890. set(icon_dependency)
  891. if(generated_icon)
  892. set(icon_dependency "${generated_icon}")
  893. endif()
  894. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  895. get_target_property(input_info_file ${source_target} JUCE_INFO_FILE)
  896. set(this_output_info_dir "${juce_library_code}/${dest_target}")
  897. set(this_output_pkginfo "${this_output_info_dir}/PkgInfo")
  898. set(this_output_plist "${this_output_info_dir}/Info.plist")
  899. get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING)
  900. _juce_execute_juceaide(plist "${juce_kind_string}" "${input_info_file}" "${this_output_plist}")
  901. set_target_properties(${dest_target} PROPERTIES
  902. BUNDLE TRUE
  903. MACOSX_BUNDLE_INFO_PLIST "${this_output_plist}")
  904. add_custom_command(OUTPUT "${this_output_pkginfo}"
  905. COMMAND juce::juceaide pkginfo "${juce_kind_string}" "${this_output_pkginfo}"
  906. VERBATIM)
  907. set(output_folder "$<TARGET_BUNDLE_CONTENT_DIR:${dest_target}>")
  908. target_sources(${dest_target} PRIVATE "${this_output_pkginfo}")
  909. set_source_files_properties("${this_output_pkginfo}" PROPERTIES
  910. HEADER_FILE_ONLY TRUE
  911. GENERATED TRUE)
  912. add_custom_command(TARGET ${dest_target} POST_BUILD
  913. COMMAND "${CMAKE_COMMAND}" -E copy "${this_output_pkginfo}" "${output_folder}"
  914. DEPENDS "${this_output_pkginfo}"
  915. VERBATIM)
  916. _juce_add_xcode_entitlements(${source_target} ${dest_target})
  917. if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  918. get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD)
  919. if(add_storyboard)
  920. get_target_property(storyboard_file ${source_target} JUCE_LAUNCH_STORYBOARD_FILE)
  921. if(NOT EXISTS "${storyboard_file}")
  922. message(FATAL_ERROR "Could not find storyboard file: ${storyboard_file}")
  923. endif()
  924. target_sources(${dest_target} PRIVATE "${storyboard_file}")
  925. set_property(TARGET ${dest_target} APPEND PROPERTY RESOURCE "${storyboard_file}")
  926. endif()
  927. endif()
  928. set_target_properties(${dest_target} PROPERTIES
  929. XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME
  930. "$<TARGET_PROPERTY:${source_target},JUCE_HARDENED_RUNTIME_ENABLED>"
  931. XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY
  932. "$<TARGET_PROPERTY:${source_target},JUCE_TARGETED_DEVICE_FAMILY>")
  933. if(juce_kind_string STREQUAL "AUv3 AppExtension")
  934. get_target_property(source_bundle_id ${source_target} JUCE_BUNDLE_ID)
  935. if(source_bundle_id MATCHES "\\.([^.]+)$")
  936. set_target_properties(${dest_target} PROPERTIES
  937. XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
  938. "${source_bundle_id}.${CMAKE_MATCH_1}AUv3")
  939. else()
  940. message(FATAL_ERROR "Bundle ID should contain at least one `.`!")
  941. endif()
  942. else()
  943. set_target_properties(${dest_target} PROPERTIES
  944. XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER
  945. $<TARGET_PROPERTY:${source_target},JUCE_BUNDLE_ID>)
  946. endif()
  947. if(CMAKE_GENERATOR STREQUAL "Xcode")
  948. get_target_property(product_name ${source_target} JUCE_PRODUCT_NAME)
  949. set(install_path "$(LOCAL_APPS_DIR)")
  950. if(juce_kind_string STREQUAL "AUv3 AppExtension")
  951. set(install_path "${install_path}/${product_name}.app")
  952. if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
  953. set(install_path "${install_path}/PlugIns")
  954. else()
  955. set(install_path "${install_path}/Contents/PlugIns")
  956. endif()
  957. endif()
  958. set_target_properties(${dest_target} PROPERTIES
  959. XCODE_ATTRIBUTE_INSTALL_PATH "${install_path}"
  960. XCODE_ATTRIBUTE_SKIP_INSTALL "NO")
  961. endif()
  962. endfunction()
  963. function(_juce_add_resources_rc source_target dest_target)
  964. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
  965. return()
  966. endif()
  967. get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  968. set(input_info_file "$<TARGET_PROPERTY:${source_target},JUCE_INFO_FILE>")
  969. get_target_property(generated_icon ${source_target} JUCE_ICON_FILE)
  970. set(dependency)
  971. if(generated_icon)
  972. set(dependency DEPENDS "${generated_icon}")
  973. endif()
  974. set(resource_rc_file "${juce_library_code}/resources.rc")
  975. add_custom_command(OUTPUT "${resource_rc_file}"
  976. COMMAND juce::juceaide rcfile "${input_info_file}" "${resource_rc_file}"
  977. ${dependency}
  978. VERBATIM)
  979. target_sources(${dest_target} PRIVATE "${resource_rc_file}")
  980. endfunction()
  981. function(_juce_configure_app_bundle source_target dest_target)
  982. set_target_properties(${dest_target} PROPERTIES
  983. JUCE_TARGET_KIND_STRING "App"
  984. MACOSX_BUNDLE TRUE
  985. WIN32_EXECUTABLE TRUE)
  986. _juce_add_resources_rc(${source_target} ${dest_target})
  987. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  988. set(nib_path "${JUCE_CMAKE_UTILS_DIR}/RecentFilesMenuTemplate.nib")
  989. target_sources("${dest_target}" PRIVATE "${nib_path}")
  990. set_source_files_properties("${nib_path}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
  991. endif()
  992. endfunction()
  993. # ==================================================================================================
  994. function(_juce_create_windows_package source_target dest_target extension default_icon x32folder x64folder)
  995. if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
  996. return()
  997. endif()
  998. get_target_property(products_folder ${dest_target} LIBRARY_OUTPUT_DIRECTORY)
  999. set(product_name $<TARGET_PROPERTY:${source_target},JUCE_PRODUCT_NAME>)
  1000. set(output_folder "${products_folder}/${product_name}.${extension}")
  1001. set(is_x64 $<EQUAL:${CMAKE_SIZEOF_VOID_P},8>)
  1002. set(arch_string $<IF:${is_x64},${x64folder},${x32folder}>)
  1003. set_target_properties(${dest_target}
  1004. PROPERTIES
  1005. PDB_OUTPUT_DIRECTORY "${products_folder}"
  1006. LIBRARY_OUTPUT_DIRECTORY "${output_folder}/Contents/${arch_string}")
  1007. get_target_property(icon_file ${source_target} JUCE_ICON_FILE)
  1008. if(NOT icon_file)
  1009. set(icon_file "${default_icon}")
  1010. endif()
  1011. if(icon_file)
  1012. set(desktop_ini "${output_folder}/desktop.ini")
  1013. set(plugin_ico "${output_folder}/Plugin.ico")
  1014. file(GENERATE OUTPUT "${desktop_ini}"
  1015. CONTENT
  1016. "[.ShellClassInfo]\nIconResource=Plugin.ico,0\nIconFile=Plugin.ico\nIconIndex=0\n")
  1017. add_custom_command(TARGET ${dest_target} POST_BUILD
  1018. COMMAND "${CMAKE_COMMAND}" -E copy "${icon_file}" "${plugin_ico}"
  1019. COMMAND attrib +s "${desktop_ini}"
  1020. COMMAND attrib +s "${output_folder}"
  1021. DEPENDS "${icon_file}" "${desktop_ini}"
  1022. VERBATIM)
  1023. endif()
  1024. endfunction()
  1025. # ==================================================================================================
  1026. function(_juce_add_unity_plugin_prefix_if_necessary name out_var)
  1027. string(TOLOWER "${name}" lower)
  1028. if(NOT lower MATCHES "^audioplugin")
  1029. set(${out_var} "audioplugin_${name}" PARENT_SCOPE)
  1030. else()
  1031. set(${out_var} "${name}" PARENT_SCOPE)
  1032. endif()
  1033. endfunction()
  1034. function(_juce_add_unity_script_file shared_target out_var)
  1035. set(script_in "${JUCE_CMAKE_UTILS_DIR}/UnityPluginGUIScript.cs.in")
  1036. get_target_property(plugin_name ${shared_target} JUCE_PLUGIN_NAME)
  1037. get_target_property(plugin_vendor ${shared_target} JUCE_COMPANY_NAME)
  1038. get_target_property(plugin_description ${shared_target} JUCE_DESCRIPTION)
  1039. string(REGEX REPLACE " +" "_" plugin_class_name "${plugin_name}")
  1040. get_target_property(juce_library_code ${shared_target} JUCE_GENERATED_SOURCES_DIRECTORY)
  1041. _juce_add_unity_plugin_prefix_if_necessary("${plugin_name}" script_prefix)
  1042. set(script_out "${juce_library_code}/${script_prefix}_UnityScript.cs")
  1043. configure_file(${script_in} ${script_out})
  1044. set(${out_var} "${script_out}" PARENT_SCOPE)
  1045. endfunction()
  1046. # ==================================================================================================
  1047. function(_juce_copy_dir target from to)
  1048. # This is a shim to make CMake copy a whole directory, rather than just
  1049. # the contents of a directory
  1050. add_custom_command(TARGET ${target} POST_BUILD
  1051. COMMAND "${CMAKE_COMMAND}"
  1052. "-Dsrc=${from}"
  1053. "-Ddest=${to}"
  1054. "-P" "${JUCE_CMAKE_UTILS_DIR}/copyDir.cmake"
  1055. VERBATIM)
  1056. endfunction()
  1057. function(_juce_set_copy_properties shared_code target from to_property)
  1058. get_target_property(destination "${shared_code}" "${to_property}")
  1059. if(destination)
  1060. set_target_properties("${target}" PROPERTIES JUCE_PLUGIN_COPY_DIR "${destination}")
  1061. endif()
  1062. set_target_properties("${target}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "${from}")
  1063. endfunction()
  1064. function(juce_enable_copy_plugin_step shared_code_target)
  1065. get_target_property(active_targets "${shared_code_target}" JUCE_ACTIVE_PLUGIN_TARGETS)
  1066. foreach(target IN LISTS active_targets)
  1067. get_target_property(source "${target}" JUCE_PLUGIN_ARTEFACT_FILE)
  1068. if(source)
  1069. get_target_property(dest "${target}" JUCE_PLUGIN_COPY_DIR)
  1070. if(dest)
  1071. _juce_copy_dir("${target}" "${source}" "$<GENEX_EVAL:${dest}>")
  1072. else()
  1073. message(WARNING "Target '${target}' requested copy but no destination is set")
  1074. endif()
  1075. endif()
  1076. endforeach()
  1077. endfunction()
  1078. # ==================================================================================================
  1079. function(_juce_set_plugin_target_properties shared_code_target kind)
  1080. set(target_name ${shared_code_target}_${kind})
  1081. set_target_properties(${target_name} PROPERTIES
  1082. ARCHIVE_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},ARCHIVE_OUTPUT_DIRECTORY>>/${kind}"
  1083. LIBRARY_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},LIBRARY_OUTPUT_DIRECTORY>>/${kind}"
  1084. RUNTIME_OUTPUT_DIRECTORY "$<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},RUNTIME_OUTPUT_DIRECTORY>>/${kind}")
  1085. get_target_property(products_folder ${target_name} LIBRARY_OUTPUT_DIRECTORY)
  1086. set(product_name $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
  1087. if(kind STREQUAL "VST3")
  1088. set_target_properties(${target_name} PROPERTIES
  1089. BUNDLE_EXTENSION vst3
  1090. PREFIX ""
  1091. SUFFIX .vst3
  1092. BUNDLE TRUE
  1093. XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst3
  1094. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  1095. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1096. _juce_create_windows_package(${shared_code_target} ${target_name} vst3 "" x86-win x86_64-win)
  1097. set(output_path "${products_folder}/${product_name}.vst3")
  1098. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  1099. set_target_properties(${target_name} PROPERTIES
  1100. SUFFIX .so
  1101. LIBRARY_OUTPUT_DIRECTORY "${output_path}/Contents/${JUCE_LINUX_TARGET_ARCHITECTURE}-linux")
  1102. endif()
  1103. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_VST3_COPY_DIR)
  1104. elseif(kind STREQUAL "VST")
  1105. set_target_properties(${target_name} PROPERTIES
  1106. BUNDLE_EXTENSION vst
  1107. BUNDLE TRUE
  1108. XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst
  1109. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  1110. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1111. set(output_path "$<TARGET_FILE:${target_name}>")
  1112. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  1113. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  1114. endif()
  1115. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_VST_COPY_DIR)
  1116. elseif(kind STREQUAL "AU")
  1117. set_target_properties(${target_name} PROPERTIES
  1118. BUNDLE_EXTENSION component
  1119. XCODE_ATTRIBUTE_WRAPPER_EXTENSION component
  1120. BUNDLE TRUE
  1121. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  1122. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1123. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  1124. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_AU_COPY_DIR)
  1125. elseif(kind STREQUAL "AUv3")
  1126. set_target_properties(${target_name} PROPERTIES
  1127. XCODE_PRODUCT_TYPE "com.apple.product-type.app-extension"
  1128. BUNDLE_EXTENSION appex
  1129. XCODE_ATTRIBUTE_WRAPPER_EXTENSION appex
  1130. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1131. elseif(kind STREQUAL "AAX")
  1132. set_target_properties(${target_name} PROPERTIES
  1133. BUNDLE_EXTENSION aaxplugin
  1134. PREFIX ""
  1135. SUFFIX .aaxplugin
  1136. XCODE_ATTRIBUTE_WRAPPER_EXTENSION aaxplugin
  1137. BUNDLE TRUE
  1138. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  1139. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1140. get_target_property(default_icon juce_aax_sdk INTERFACE_JUCE_AAX_DEFAULT_ICON)
  1141. _juce_create_windows_package(${shared_code_target} ${target_name} aaxplugin "${default_icon}" Win32 x64)
  1142. set(output_path "${products_folder}/${product_name}.aaxplugin")
  1143. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_AAX_COPY_DIR)
  1144. elseif(kind STREQUAL "Unity")
  1145. set_target_properties(${target_name} PROPERTIES
  1146. BUNDLE_EXTENSION bundle
  1147. XCODE_ATTRIBUTE_WRAPPER_EXTENSION bundle
  1148. BUNDLE TRUE
  1149. XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle
  1150. XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES)
  1151. _juce_add_unity_script_file(${shared_code_target} script_file)
  1152. target_sources(${target_name} PRIVATE "${script_file}")
  1153. set_source_files_properties("${script_file}" PROPERTIES
  1154. GENERATED TRUE
  1155. MACOSX_PACKAGE_LOCATION Resources)
  1156. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  1157. set(output_path "$<TARGET_BUNDLE_DIR:${target_name}>")
  1158. _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_UNITY_COPY_DIR)
  1159. else()
  1160. # On windows and linux, the gui script needs to be copied next to the unity output
  1161. add_custom_command(TARGET ${target_name} POST_BUILD
  1162. COMMAND "${CMAKE_COMMAND}" -E copy "${script_file}" "${products_folder}"
  1163. DEPENDS "${script_file}"
  1164. VERBATIM)
  1165. _juce_set_copy_properties(${shared_code_target}
  1166. ${target_name}
  1167. "$<TARGET_FILE:${target_name}>"
  1168. JUCE_UNITY_COPY_DIR)
  1169. _juce_set_copy_properties(${shared_code_target}
  1170. ${target_name}
  1171. "${script_file}"
  1172. JUCE_UNITY_COPY_DIR)
  1173. endif()
  1174. endif()
  1175. endfunction()
  1176. # Place plugin wrapper targets alongside the shared code target in IDEs
  1177. function(_juce_set_plugin_folder_property shared_target wrapper_target)
  1178. get_target_property(folder_to_use "${shared_target}" FOLDER)
  1179. if(folder_to_use STREQUAL "folder_to_use-NOTFOUND")
  1180. set_target_properties("${shared_target}" PROPERTIES FOLDER "${shared_target}")
  1181. elseif(NOT folder_to_use MATCHES ".*${shared_target}$")
  1182. set_target_properties("${shared_target}" PROPERTIES FOLDER "${folder_to_use}/${shared_target}")
  1183. endif()
  1184. get_target_property(folder_to_use "${shared_target}" FOLDER)
  1185. set_target_properties("${wrapper_target}" PROPERTIES FOLDER "${folder_to_use}")
  1186. endfunction()
  1187. # Convert the cmake plugin kind ids to strings understood by ProjectType::Target::typeFromName
  1188. function(_juce_get_plugin_kind_name kind out_var)
  1189. if(kind STREQUAL "AU")
  1190. set(${out_var} "AU" PARENT_SCOPE)
  1191. elseif(kind STREQUAL "AUv3")
  1192. set(${out_var} "AUv3 AppExtension" PARENT_SCOPE)
  1193. elseif(kind STREQUAL "AAX")
  1194. set(${out_var} "AAX" PARENT_SCOPE)
  1195. elseif(kind STREQUAL "Standalone")
  1196. set(${out_var} "Standalone Plugin" PARENT_SCOPE)
  1197. elseif(kind STREQUAL "Unity")
  1198. set(${out_var} "Unity Plugin" PARENT_SCOPE)
  1199. elseif(kind STREQUAL "VST")
  1200. set(${out_var} "VST" PARENT_SCOPE)
  1201. elseif(kind STREQUAL "VST3")
  1202. set(${out_var} "VST3" PARENT_SCOPE)
  1203. endif()
  1204. endfunction()
  1205. function(_juce_link_plugin_wrapper shared_code_target kind)
  1206. set(target_name ${shared_code_target}_${kind})
  1207. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  1208. add_library(${target_name} SHARED)
  1209. elseif((kind STREQUAL "Standalone") OR (kind STREQUAL "AUv3"))
  1210. add_executable(${target_name} WIN32 MACOSX_BUNDLE)
  1211. else()
  1212. add_library(${target_name} MODULE)
  1213. endif()
  1214. if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
  1215. target_link_libraries(${target_name} PRIVATE "-Wl,--no-undefined")
  1216. endif()
  1217. # We re-export the shared code's private include dirs, because the wrapper targets need to
  1218. # see the module headers. We don't just link publicly, because that would introduce
  1219. # conflicting macro definitions.
  1220. target_include_directories(${target_name} PRIVATE
  1221. $<TARGET_PROPERTY:${shared_code_target},INCLUDE_DIRECTORIES>)
  1222. target_link_libraries(${target_name} PRIVATE
  1223. ${shared_code_target}
  1224. juce::juce_audio_plugin_client_${kind})
  1225. _juce_set_output_name(${target_name} $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
  1226. _juce_set_plugin_folder_property("${shared_code_target}" "${target_name}")
  1227. _juce_get_plugin_kind_name(${kind} juce_kind_string)
  1228. set_target_properties(${target_name} PROPERTIES
  1229. XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO
  1230. XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES YES
  1231. POSITION_INDEPENDENT_CODE TRUE
  1232. VISIBILITY_INLINES_HIDDEN TRUE
  1233. C_VISIBILITY_PRESET hidden
  1234. CXX_VISIBILITY_PRESET hidden
  1235. JUCE_TARGET_KIND_STRING "${juce_kind_string}")
  1236. add_dependencies(${shared_code_target}_All ${target_name})
  1237. _juce_configure_bundle(${shared_code_target} ${target_name})
  1238. _juce_set_plugin_target_properties(${shared_code_target} ${kind})
  1239. endfunction()
  1240. # ==================================================================================================
  1241. function(_juce_get_vst3_category_string target out_var)
  1242. get_target_property(vst3_categories ${target} JUCE_VST3_CATEGORIES)
  1243. if((NOT Fx IN_LIST vst3_categories) AND (NOT Instrument IN_LIST vst3_categories))
  1244. get_target_property(is_synth ${target} JUCE_IS_SYNTH)
  1245. if(is_synth)
  1246. set(first_type Instrument)
  1247. else()
  1248. set(first_type Fx)
  1249. endif()
  1250. list(INSERT vst3_categories 0 ${first_type})
  1251. else()
  1252. if(Instrument IN_LIST vst3_categories)
  1253. list(REMOVE_ITEM vst3_categories Instrument)
  1254. list(INSERT vst3_categories 0 Instrument)
  1255. endif()
  1256. if(Fx IN_LIST vst3_categories)
  1257. list(REMOVE_ITEM vst3_categories Fx)
  1258. list(INSERT vst3_categories 0 Fx)
  1259. endif()
  1260. endif()
  1261. string(REGEX REPLACE ";" "|" result "${vst3_categories}")
  1262. set(${out_var} ${result} PARENT_SCOPE)
  1263. endfunction()
  1264. function(_juce_configure_plugin_targets target)
  1265. if(CMAKE_VERSION VERSION_LESS "3.15.0")
  1266. message(FATAL_ERROR "Plugin targets require CMake 3.15 or higher")
  1267. endif()
  1268. _juce_set_output_name(${target} $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>_SharedCode)
  1269. target_link_libraries(${target} PRIVATE juce::juce_audio_plugin_client_utils)
  1270. get_target_property(enabled_formats ${target} JUCE_FORMATS)
  1271. set(active_formats)
  1272. _juce_get_platform_plugin_kinds(plugin_kinds)
  1273. foreach(kind IN LISTS plugin_kinds)
  1274. if(kind IN_LIST enabled_formats)
  1275. list(APPEND active_formats "${kind}")
  1276. endif()
  1277. endforeach()
  1278. if((VST IN_LIST active_formats) AND (NOT TARGET juce_vst2_sdk))
  1279. message(FATAL_ERROR "Use juce_set_vst2_sdk_path to set up the VST sdk before adding VST targets")
  1280. elseif((AAX IN_LIST active_formats) AND (NOT TARGET juce_aax_sdk))
  1281. message(FATAL_ERROR "Use juce_set_aax_sdk_path to set up the AAX sdk before adding AAX targets")
  1282. endif()
  1283. _juce_add_standard_defs(${target})
  1284. _juce_add_plugin_definitions(${target} PRIVATE ${active_formats})
  1285. # The plugin wrappers need to know what other modules are available, especially
  1286. # juce_audio_utils and juce_gui_basics. We achieve this by searching for
  1287. # JUCE_MODULE_AVAILABLE_ private compile definitions, and reexporting them in
  1288. # the interface compile definitions.
  1289. # Unfortunately this requires CMake 3.15.
  1290. _juce_get_module_definitions(${target} ON enabled_modules)
  1291. target_compile_definitions(${target} INTERFACE ${enabled_modules})
  1292. target_compile_definitions(${target} PRIVATE JUCE_SHARED_CODE=1)
  1293. get_target_property(project_version_string ${target} JUCE_VERSION)
  1294. _juce_version_code(${project_version_string} project_version_hex)
  1295. get_target_property(project_manufacturer_code ${target} JUCE_PLUGIN_MANUFACTURER_CODE)
  1296. get_target_property(project_plugin_code ${target} JUCE_PLUGIN_CODE)
  1297. get_target_property(use_legacy_compatibility_plugin_code ${target} JUCE_USE_LEGACY_COMPATIBILITY_PLUGIN_CODE)
  1298. if(use_legacy_compatibility_plugin_code)
  1299. set(project_manufacturer_code "project_manufacturer_code-NOTFOUND")
  1300. endif()
  1301. _juce_to_char_literal(${project_manufacturer_code} project_manufacturer_code)
  1302. _juce_to_char_literal(${project_plugin_code} project_plugin_code)
  1303. _juce_get_vst3_category_string(${target} vst3_category_string)
  1304. target_compile_definitions(${target} PUBLIC
  1305. JUCE_STANDALONE_APPLICATION=JucePlugin_Build_Standalone
  1306. JucePlugin_IsSynth=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_SYNTH>>
  1307. JucePlugin_ManufacturerCode=0x${project_manufacturer_code}
  1308. JucePlugin_Manufacturer="$<TARGET_PROPERTY:${target},JUCE_COMPANY_NAME>"
  1309. JucePlugin_ManufacturerWebsite="$<TARGET_PROPERTY:${target},JUCE_COMPANY_WEBSITE>"
  1310. JucePlugin_ManufacturerEmail="$<TARGET_PROPERTY:${target},JUCE_COMPANY_EMAIL>"
  1311. JucePlugin_PluginCode=0x${project_plugin_code}
  1312. JucePlugin_ProducesMidiOutput=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_NEEDS_MIDI_OUTPUT>>
  1313. JucePlugin_IsMidiEffect=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_MIDI_EFFECT>>
  1314. JucePlugin_WantsMidiInput=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_NEEDS_MIDI_INPUT>>
  1315. JucePlugin_EditorRequiresKeyboardFocus=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_EDITOR_WANTS_KEYBOARD_FOCUS>>
  1316. JucePlugin_Name="$<TARGET_PROPERTY:${target},JUCE_PLUGIN_NAME>"
  1317. JucePlugin_Desc="$<TARGET_PROPERTY:${target},JUCE_DESCRIPTION>"
  1318. JucePlugin_Version=${project_version_string}
  1319. JucePlugin_VersionString="${project_version_string}"
  1320. JucePlugin_VersionCode=0x${project_version_hex}
  1321. JucePlugin_VSTUniqueID=JucePlugin_PluginCode
  1322. JucePlugin_VSTCategory=$<TARGET_PROPERTY:${target},JUCE_VST2_CATEGORY>
  1323. JucePlugin_Vst3Category="${vst3_category_string}"
  1324. JucePlugin_AUMainType=$<TARGET_PROPERTY:${target},JUCE_AU_MAIN_TYPE_CODE>
  1325. JucePlugin_AUSubType=JucePlugin_PluginCode
  1326. JucePlugin_AUExportPrefix=$<TARGET_PROPERTY:${target},JUCE_AU_EXPORT_PREFIX>
  1327. JucePlugin_AUExportPrefixQuoted="$<TARGET_PROPERTY:${target},JUCE_AU_EXPORT_PREFIX>"
  1328. JucePlugin_AUManufacturerCode=JucePlugin_ManufacturerCode
  1329. JucePlugin_CFBundleIdentifier=$<TARGET_PROPERTY:${target},JUCE_BUNDLE_ID>
  1330. JucePlugin_AAXIdentifier=$<TARGET_PROPERTY:${target},JUCE_AAX_IDENTIFIER>
  1331. JucePlugin_AAXManufacturerCode=JucePlugin_ManufacturerCode
  1332. JucePlugin_AAXProductId=JucePlugin_PluginCode
  1333. JucePlugin_AAXCategory=$<TARGET_PROPERTY:${target},JUCE_AAX_CATEGORY>
  1334. JucePlugin_AAXDisableBypass=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_BYPASS>>
  1335. JucePlugin_AAXDisableMultiMono=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_MULTI_MONO>>
  1336. JucePlugin_VSTNumMidiInputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_INS>
  1337. JucePlugin_VSTNumMidiOutputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_OUTS>)
  1338. set_target_properties(${target} PROPERTIES
  1339. POSITION_INDEPENDENT_CODE TRUE
  1340. INTERFACE_POSITION_INDEPENDENT_CODE TRUE
  1341. VISIBILITY_INLINES_HIDDEN TRUE
  1342. C_VISIBILITY_PRESET hidden
  1343. CXX_VISIBILITY_PRESET hidden)
  1344. # A convenience target for building all plugin variations at once
  1345. add_custom_target(${target}_All)
  1346. _juce_set_plugin_folder_property("${target}" "${target}_All")
  1347. foreach(kind IN LISTS active_formats)
  1348. _juce_link_plugin_wrapper(${target} ${kind})
  1349. if(TARGET ${target}_${kind})
  1350. list(APPEND active_plugin_targets ${target}_${kind})
  1351. endif()
  1352. endforeach()
  1353. set_target_properties(${target} PROPERTIES JUCE_ACTIVE_PLUGIN_TARGETS "${active_plugin_targets}")
  1354. if(TARGET ${target}_Standalone)
  1355. _juce_configure_app_bundle(${target} ${target}_Standalone)
  1356. endif()
  1357. if(TARGET ${target}_AU)
  1358. _juce_add_au_resource_fork(${target} ${target}_AU)
  1359. endif()
  1360. if(TARGET ${target}_AAX)
  1361. target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk)
  1362. endif()
  1363. if((TARGET ${target}_AUv3) AND (TARGET ${target}_Standalone))
  1364. add_dependencies(${target}_Standalone ${target}_AUv3)
  1365. # Copy the AUv3 into the Standalone app bundle
  1366. _juce_copy_dir(${target}_Standalone
  1367. "$<TARGET_BUNDLE_DIR:${target}_AUv3>"
  1368. "$<TARGET_BUNDLE_CONTENT_DIR:${target}_Standalone>/PlugIns")
  1369. endif()
  1370. get_target_property(wants_copy "${target}" JUCE_COPY_PLUGIN_AFTER_BUILD)
  1371. if(wants_copy)
  1372. juce_enable_copy_plugin_step("${target}")
  1373. endif()
  1374. endfunction()
  1375. # ==================================================================================================
  1376. function(_juce_set_generic_property_if_not_set target property)
  1377. list(LENGTH ARGN num_extra_args)
  1378. if(num_extra_args EQUAL 0)
  1379. return()
  1380. endif()
  1381. set(existing_property)
  1382. get_target_property(existing_property ${target} ${property})
  1383. if(existing_property STREQUAL "existing_property-NOTFOUND")
  1384. set_target_properties(${target} PROPERTIES ${property} "${ARGN}")
  1385. endif()
  1386. endfunction()
  1387. function(_juce_set_property_if_not_set target property)
  1388. _juce_set_generic_property_if_not_set(${target} JUCE_${property} ${ARGN})
  1389. endfunction()
  1390. function(_juce_make_valid_4cc out_var)
  1391. string(RANDOM LENGTH 1 ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" head)
  1392. string(RANDOM LENGTH 3 ALPHABET "abcdefghijklmnopqrstuvwxyz" tail)
  1393. set(${out_var} "${head}${tail}" PARENT_SCOPE)
  1394. endfunction()
  1395. # This function adds some default properties that plugin targets expect to be
  1396. # set, in order to generate the correct compile definitions.
  1397. function(_juce_set_fallback_properties target)
  1398. _juce_set_property_if_not_set(${target} PRODUCT_NAME ${target})
  1399. get_target_property(output_name ${target} JUCE_PRODUCT_NAME)
  1400. _juce_set_property_if_not_set(${target} DESCRIPTION "${output_name}")
  1401. _juce_set_property_if_not_set(${target} PLUGIN_NAME "${output_name}")
  1402. get_target_property(real_company_name ${target} JUCE_COMPANY_NAME)
  1403. _juce_set_property_if_not_set(${target} BUNDLE_ID "com.${real_company_name}.${target}")
  1404. _juce_set_property_if_not_set(${target} VERSION ${PROJECT_VERSION})
  1405. get_target_property(final_version ${target} JUCE_VERSION)
  1406. if(NOT final_version)
  1407. message(FATAL_ERROR "Target ${target} must have its VERSION argument set, or must be part of a project with a PROJECT_VERSION")
  1408. endif()
  1409. _juce_set_property_if_not_set(${target} BUILD_VERSION "${final_version}")
  1410. get_target_property(custom_xcassets ${target} JUCE_CUSTOM_XCASSETS_FOLDER)
  1411. set(needs_storyboard TRUE)
  1412. if(custom_xcassets)
  1413. set(needs_storyboard FALSE)
  1414. endif()
  1415. set_target_properties(${target} PROPERTIES JUCE_SHOULD_ADD_STORYBOARD ${needs_storyboard})
  1416. _juce_set_property_if_not_set(${target} IPHONE_SCREEN_ORIENTATIONS
  1417. UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft
  1418. UIInterfaceOrientationLandscapeRight)
  1419. _juce_set_property_if_not_set(${target} IPAD_SCREEN_ORIENTATIONS
  1420. UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft
  1421. UIInterfaceOrientationLandscapeRight)
  1422. _juce_set_property_if_not_set(${target}
  1423. LAUNCH_STORYBOARD_FILE "${JUCE_CMAKE_UTILS_DIR}/LaunchScreen.storyboard")
  1424. _juce_set_property_if_not_set(${target} PLUGIN_MANUFACTURER_CODE "Manu")
  1425. # The plugin code will change on each run, unless you specify one manually!
  1426. _juce_make_valid_4cc(random_code)
  1427. _juce_set_property_if_not_set(${target} PLUGIN_CODE ${random_code})
  1428. _juce_set_property_if_not_set(${target} IS_SYNTH FALSE)
  1429. _juce_set_property_if_not_set(${target} NEEDS_MIDI_INPUT FALSE)
  1430. _juce_set_property_if_not_set(${target} NEEDS_MIDI_OUTPUT FALSE)
  1431. _juce_set_property_if_not_set(${target} IS_MIDI_EFFECT FALSE)
  1432. _juce_set_property_if_not_set(${target} EDITOR_WANTS_KEYBOARD_FOCUS FALSE)
  1433. _juce_set_property_if_not_set(${target} DISABLE_AAX_BYPASS FALSE)
  1434. _juce_set_property_if_not_set(${target} DISABLE_AAX_MULTI_MONO FALSE)
  1435. _juce_set_property_if_not_set(${target} PLUGINHOST_AU FALSE)
  1436. get_target_property(bundle_id ${target} JUCE_BUNDLE_ID)
  1437. _juce_set_property_if_not_set(${target} AAX_IDENTIFIER ${bundle_id})
  1438. _juce_set_property_if_not_set(${target} VST_NUM_MIDI_INS 16)
  1439. _juce_set_property_if_not_set(${target} VST_NUM_MIDI_OUTS 16)
  1440. _juce_set_property_if_not_set(${target} AU_SANDBOX_SAFE FALSE)
  1441. _juce_set_property_if_not_set(${target} SUPPRESS_AU_PLIST_RESOURCE_USAGE FALSE)
  1442. _juce_set_property_if_not_set(${target} HARDENED_RUNTIME_ENABLED NO)
  1443. _juce_set_property_if_not_set(${target} APP_SANDBOX_ENABLED NO)
  1444. _juce_set_property_if_not_set(${target} APP_SANDBOX_INHERIT NO)
  1445. get_target_property(is_synth ${target} JUCE_IS_SYNTH)
  1446. # VST3_CATEGORIES
  1447. if(is_synth)
  1448. _juce_set_property_if_not_set(${target} VST3_CATEGORIES Instrument Synth)
  1449. else()
  1450. _juce_set_property_if_not_set(${target} VST3_CATEGORIES Fx)
  1451. endif()
  1452. # VST2_CATEGORY
  1453. if(is_synth)
  1454. _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategSynth)
  1455. else()
  1456. _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategEffect)
  1457. endif()
  1458. get_target_property(is_midi_effect ${target} JUCE_IS_MIDI_EFFECT)
  1459. get_target_property(needs_midi_input ${target} JUCE_NEEDS_MIDI_INPUT)
  1460. # AU MAIN TYPE
  1461. if(is_midi_effect)
  1462. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MIDIProcessor)
  1463. elseif(is_synth)
  1464. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MusicDevice)
  1465. elseif(needs_midi_input)
  1466. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_MusicEffect)
  1467. else()
  1468. _juce_set_property_if_not_set(${target} AU_MAIN_TYPE kAudioUnitType_Effect)
  1469. endif()
  1470. _juce_set_property_if_not_set(${target} TARGETED_DEVICE_FAMILY "1,2")
  1471. set(au_category_codes
  1472. 'aufx'
  1473. 'aufc'
  1474. 'augn'
  1475. 'aumi'
  1476. 'aumx'
  1477. 'aumu'
  1478. 'aumf'
  1479. 'auol'
  1480. 'auou'
  1481. 'aupn')
  1482. set(au_category_strings
  1483. kAudioUnitType_Effect
  1484. kAudioUnitType_FormatConverter
  1485. kAudioUnitType_Generator
  1486. kAudioUnitType_MIDIProcessor
  1487. kAudioUnitType_Mixer
  1488. kAudioUnitType_MusicDevice
  1489. kAudioUnitType_MusicEffect
  1490. kAudioUnitType_OfflineEffect
  1491. kAudioUnitType_Output
  1492. kAudioUnitType_Panner)
  1493. # AU export prefix
  1494. string(MAKE_C_IDENTIFIER ${output_name} au_prefix)
  1495. set(au_prefix "${au_prefix}AU")
  1496. _juce_set_property_if_not_set(${target} AU_EXPORT_PREFIX ${au_prefix})
  1497. # Find appropriate AU category code
  1498. get_target_property(actual_au_category ${target} JUCE_AU_MAIN_TYPE)
  1499. list(FIND au_category_strings ${actual_au_category} au_index)
  1500. if(au_index GREATER_EQUAL 0)
  1501. list(GET au_category_codes ${au_index} au_code_representation)
  1502. set_target_properties(${target} PROPERTIES JUCE_AU_MAIN_TYPE_CODE ${au_code_representation})
  1503. endif()
  1504. # AAX category
  1505. # The order of these strings is important, as the index of each string
  1506. # will be used to set an appropriate bit in the category bitfield.
  1507. set(aax_category_strings
  1508. ePlugInCategory_None
  1509. ePlugInCategory_EQ
  1510. ePlugInCategory_Dynamics
  1511. ePlugInCategory_PitchShift
  1512. ePlugInCategory_Reverb
  1513. ePlugInCategory_Delay
  1514. ePlugInCategory_Modulation
  1515. ePlugInCategory_Harmonic
  1516. ePlugInCategory_NoiseReduction
  1517. ePlugInCategory_Dither
  1518. ePlugInCategory_SoundField
  1519. ePlugInCategory_HWGenerators
  1520. ePlugInCategory_SWGenerators
  1521. ePlugInCategory_WrappedPlugin
  1522. ePlugInCategory_Effect)
  1523. if(is_synth)
  1524. set(default_aax_category ePlugInCategory_SWGenerators)
  1525. else()
  1526. set(default_aax_category ePlugInCategory_None)
  1527. endif()
  1528. _juce_set_property_if_not_set(${target} AAX_CATEGORY ${default_aax_category})
  1529. # Replace AAX category string with its integral representation
  1530. get_target_property(actual_aax_category ${target} JUCE_AAX_CATEGORY)
  1531. set(aax_category_int "")
  1532. foreach(category_string IN LISTS actual_aax_category)
  1533. list(FIND aax_category_strings ${category_string} aax_index)
  1534. if(aax_index GREATER_EQUAL 0)
  1535. if(aax_index EQUAL 0)
  1536. set(aax_category_bit 0)
  1537. else()
  1538. set(aax_category_bit "1 << (${aax_index} - 1)")
  1539. endif()
  1540. if(aax_category_int STREQUAL "")
  1541. set(aax_category_int 0)
  1542. endif()
  1543. math(EXPR aax_category_int "${aax_category_int} | (${aax_category_bit})")
  1544. endif()
  1545. endforeach()
  1546. if(NOT aax_category_int STREQUAL "")
  1547. set_target_properties(${target} PROPERTIES JUCE_AAX_CATEGORY ${aax_category_int})
  1548. endif()
  1549. endfunction()
  1550. # ==================================================================================================
  1551. function(_juce_initialise_target target)
  1552. set(one_value_args
  1553. VERSION
  1554. BUILD_VERSION
  1555. PRODUCT_NAME
  1556. PLIST_TO_MERGE
  1557. BUNDLE_ID
  1558. MICROPHONE_PERMISSION_ENABLED
  1559. MICROPHONE_PERMISSION_TEXT
  1560. CAMERA_PERMISSION_ENABLED
  1561. CAMERA_PERMISSION_TEXT
  1562. SEND_APPLE_EVENTS_PERMISSION_ENABLED
  1563. SEND_APPLE_EVENTS_PERMISSION_TEXT
  1564. BLUETOOTH_PERMISSION_ENABLED
  1565. BLUETOOTH_PERMISSION_TEXT
  1566. FILE_SHARING_ENABLED # iOS only
  1567. DOCUMENT_BROWSER_ENABLED # iOS only
  1568. LAUNCH_STORYBOARD_FILE # iOS only
  1569. APP_GROUPS_ENABLED # iOS only
  1570. ICLOUD_PERMISSIONS_ENABLED # iOS only
  1571. STATUS_BAR_HIDDEN # iOS only
  1572. BACKGROUND_AUDIO_ENABLED # iOS only
  1573. BACKGROUND_BLE_ENABLED # iOS only
  1574. CUSTOM_XCASSETS_FOLDER # iOS only
  1575. TARGETED_DEVICE_FAMILY # iOS only
  1576. REQUIRES_FULL_SCREEN # iOS only
  1577. ICON_BIG
  1578. ICON_SMALL
  1579. COMPANY_COPYRIGHT
  1580. COMPANY_NAME
  1581. COMPANY_WEBSITE
  1582. COMPANY_EMAIL
  1583. NEEDS_CURL # Set this true if you want to link curl on Linux
  1584. NEEDS_WEB_BROWSER # Set this true if you want to link webkit on Linux
  1585. NEEDS_STORE_KIT # Set this true if you want in-app-purchases on Mac
  1586. PUSH_NOTIFICATIONS_ENABLED
  1587. HARDENED_RUNTIME_ENABLED
  1588. APP_SANDBOX_ENABLED
  1589. APP_SANDBOX_INHERIT
  1590. PLUGIN_NAME
  1591. PLUGIN_MANUFACTURER_CODE
  1592. PLUGIN_CODE
  1593. DESCRIPTION
  1594. IS_SYNTH
  1595. NEEDS_MIDI_INPUT
  1596. NEEDS_MIDI_OUTPUT
  1597. IS_MIDI_EFFECT
  1598. EDITOR_WANTS_KEYBOARD_FOCUS
  1599. DISABLE_AAX_BYPASS
  1600. DISABLE_AAX_MULTI_MONO
  1601. AAX_IDENTIFIER
  1602. VST_NUM_MIDI_INS
  1603. VST_NUM_MIDI_OUTS
  1604. VST2_CATEGORY
  1605. AU_MAIN_TYPE
  1606. AU_EXPORT_PREFIX
  1607. AU_SANDBOX_SAFE
  1608. SUPPRESS_AU_PLIST_RESOURCE_USAGE
  1609. PLUGINHOST_AU # Set this true if you want to host AU plugins
  1610. USE_LEGACY_COMPATIBILITY_PLUGIN_CODE
  1611. VST_COPY_DIR
  1612. VST3_COPY_DIR
  1613. AAX_COPY_DIR
  1614. AU_COPY_DIR
  1615. UNITY_COPY_DIR
  1616. COPY_PLUGIN_AFTER_BUILD)
  1617. set(multi_value_args
  1618. FORMATS
  1619. VST3_CATEGORIES
  1620. HARDENED_RUNTIME_OPTIONS
  1621. APP_SANDBOX_OPTIONS
  1622. DOCUMENT_EXTENSIONS
  1623. AAX_CATEGORY
  1624. IPHONE_SCREEN_ORIENTATIONS # iOS only
  1625. IPAD_SCREEN_ORIENTATIONS # iOS only
  1626. APP_GROUP_IDS) # iOS only
  1627. cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
  1628. set(base_folder "${CMAKE_CURRENT_BINARY_DIR}/${target}_artefacts")
  1629. set(products_folder "${base_folder}/$<CONFIG>")
  1630. set(juce_library_code "${base_folder}/JuceLibraryCode")
  1631. set_target_properties(${target} PROPERTIES JUCE_GENERATED_SOURCES_DIRECTORY "${juce_library_code}")
  1632. set_target_properties(${target} PROPERTIES
  1633. ARCHIVE_OUTPUT_DIRECTORY "${products_folder}"
  1634. LIBRARY_OUTPUT_DIRECTORY "${products_folder}"
  1635. RUNTIME_OUTPUT_DIRECTORY "${products_folder}")
  1636. if(JUCE_ARG_ICON_BIG)
  1637. _juce_make_absolute_and_check(JUCE_ARG_ICON_BIG)
  1638. endif()
  1639. if(JUCE_ARG_ICON_SMALL)
  1640. _juce_make_absolute_and_check(JUCE_ARG_ICON_SMALL)
  1641. endif()
  1642. set(inherited_properties
  1643. COMPANY_NAME
  1644. COMPANY_WEBSITE
  1645. COMPANY_EMAIL
  1646. COMPANY_COPYRIGHT
  1647. VST_COPY_DIR
  1648. VST3_COPY_DIR
  1649. AU_COPY_DIR
  1650. AAX_COPY_DIR
  1651. UNITY_COPY_DIR
  1652. COPY_PLUGIN_AFTER_BUILD)
  1653. # Overwrite any properties that might be inherited
  1654. foreach(prop_string IN LISTS inherited_properties)
  1655. if(NOT ${JUCE_ARG_${prop_string}} STREQUAL "")
  1656. set_target_properties(${target} PROPERTIES JUCE_${prop_string} "${JUCE_ARG_${prop_string}}")
  1657. endif()
  1658. endforeach()
  1659. # Add each of the function arguments as target properties, so that it's easier to
  1660. # extract them in other functions
  1661. foreach(arg_string IN LISTS one_value_args multi_value_args)
  1662. _juce_set_property_if_not_set(${target} ${arg_string} "${JUCE_ARG_${arg_string}}")
  1663. endforeach()
  1664. _juce_set_fallback_properties(${target})
  1665. target_include_directories(${target} PRIVATE
  1666. $<TARGET_PROPERTY:${target},JUCE_GENERATED_SOURCES_DIRECTORY>)
  1667. target_link_libraries(${target} PUBLIC $<$<TARGET_EXISTS:juce_vst2_sdk>:juce_vst2_sdk>)
  1668. get_target_property(is_pluginhost_au ${target} JUCE_PLUGINHOST_AU)
  1669. if(is_pluginhost_au)
  1670. target_compile_definitions(${target} PUBLIC JUCE_PLUGINHOST_AU=1)
  1671. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
  1672. _juce_link_frameworks("${target}" PRIVATE CoreAudioKit)
  1673. endif()
  1674. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  1675. _juce_link_frameworks("${target}" PRIVATE AudioUnit)
  1676. endif()
  1677. endif()
  1678. _juce_write_generate_time_info(${target})
  1679. _juce_link_optional_libraries(${target})
  1680. if(JUCE_ENABLE_MODULE_SOURCE_GROUPS)
  1681. get_property(all_modules GLOBAL PROPERTY _juce_module_names)
  1682. foreach(module_name IN LISTS all_modules)
  1683. get_target_property(path ${module_name} INTERFACE_JUCE_MODULE_PATH)
  1684. get_target_property(header_files ${module_name} INTERFACE_JUCE_MODULE_HEADERS)
  1685. get_target_property(source_files ${module_name} INTERFACE_JUCE_MODULE_SOURCES)
  1686. source_group(TREE ${path} PREFIX "JUCE Modules" FILES ${header_files} ${source_files})
  1687. set_source_files_properties(${header_files} PROPERTIES HEADER_FILE_ONLY TRUE)
  1688. endforeach()
  1689. endif()
  1690. endfunction()
  1691. # ==================================================================================================
  1692. function(juce_add_console_app target)
  1693. add_executable(${target})
  1694. target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1)
  1695. if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  1696. target_compile_definitions(${target} PRIVATE _CONSOLE=1)
  1697. endif()
  1698. _juce_initialise_target(${target} ${ARGN})
  1699. endfunction()
  1700. function(juce_add_gui_app target)
  1701. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  1702. add_library(${target} SHARED)
  1703. else()
  1704. add_executable(${target})
  1705. endif()
  1706. target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1)
  1707. _juce_initialise_target(${target} ${ARGN})
  1708. _juce_set_output_name(${target} $<TARGET_PROPERTY:${target},JUCE_PRODUCT_NAME>)
  1709. set_target_properties(${target} PROPERTIES JUCE_TARGET_KIND_STRING "App")
  1710. _juce_configure_bundle(${target} ${target})
  1711. _juce_configure_app_bundle(${target} ${target})
  1712. endfunction()
  1713. function(juce_add_plugin target)
  1714. add_library(${target} STATIC)
  1715. set_target_properties(${target} PROPERTIES JUCE_IS_PLUGIN TRUE)
  1716. _juce_initialise_target(${target} ${ARGN})
  1717. _juce_configure_plugin_targets(${target})
  1718. endfunction()
  1719. # ==================================================================================================
  1720. function(_juce_target_args_from_plugin_characteristics out_var)
  1721. set(pairs
  1722. "pluginIsSynth\;IS_SYNTH"
  1723. "pluginWantsMidiIn\;NEEDS_MIDI_INPUT"
  1724. "pluginProducesMidiOut\;NEEDS_MIDI_OUTPUT"
  1725. "pluginIsMidiEffectPlugin\;IS_MIDI_EFFECT"
  1726. "pluginEditorRequiresKeys\;EDITOR_WANTS_KEYBOARD_FOCUS")
  1727. set(result)
  1728. foreach(pair IN LISTS pairs)
  1729. list(GET pair 0 old_key)
  1730. if("${old_key}" IN_LIST ARGN)
  1731. list(GET pair 1 new_key)
  1732. list(APPEND result ${new_key} TRUE)
  1733. endif()
  1734. endforeach()
  1735. set(${out_var} ${result} PARENT_SCOPE)
  1736. endfunction()
  1737. # ==================================================================================================
  1738. function(_juce_get_pip_targets pip out_var)
  1739. set(test_targets "${pip}")
  1740. _juce_get_all_plugin_kinds(plugin_kinds)
  1741. foreach(plugin_kind IN LISTS plugin_kinds)
  1742. list(APPEND test_targets "${JUCE_PIP_NAME}_${plugin_kind}")
  1743. endforeach()
  1744. set(${out_var} ${test_targets} PARENT_SCOPE)
  1745. endfunction()
  1746. function(juce_add_pip header)
  1747. _juce_make_absolute(header)
  1748. _juce_extract_metadata_block(JUCE_PIP_METADATA "${header}" metadata_dict)
  1749. _juce_get_metadata("${metadata_dict}" name JUCE_PIP_NAME)
  1750. if(NOT JUCE_PIP_NAME)
  1751. message(FATAL_ERROR "Error in '${header}': PIP headers must declare a `name` field")
  1752. endif()
  1753. string(MAKE_C_IDENTIFIER "${JUCE_PIP_NAME}" pip_name_sanitised)
  1754. if(NOT JUCE_PIP_NAME STREQUAL pip_name_sanitised)
  1755. message(FATAL_ERROR "Error in '${header}': PIP `name` value '${JUCE_PIP_NAME}' must be a valid C identifier")
  1756. endif()
  1757. if(TARGET "${JUCE_PIP_NAME}")
  1758. # We already added a target with this name, let's try using the filename instead
  1759. get_filename_component(JUCE_PIP_NAME "${header}" NAME_WE)
  1760. endif()
  1761. if(TARGET "${JUCE_PIP_NAME}")
  1762. message(FATAL_ERROR "Error in '${header}': Could not create a unique target name for PIP ${header}")
  1763. endif()
  1764. _juce_get_metadata("${metadata_dict}" type pip_kind)
  1765. if(NOT pip_kind)
  1766. message(FATAL_ERROR "Error in '${header}': PIP headers must declare a `type` field")
  1767. endif()
  1768. _juce_get_metadata("${metadata_dict}" pluginCharacteristics pip_charateristics)
  1769. _juce_target_args_from_plugin_characteristics(extra_target_args ${pip_charateristics})
  1770. list(APPEND extra_target_args
  1771. NEEDS_CURL TRUE
  1772. NEEDS_WEB_BROWSER TRUE)
  1773. _juce_get_metadata("${metadata_dict}" moduleFlags pip_moduleflags)
  1774. if("JUCE_IN_APP_PURCHASES=1" IN_LIST pip_moduleflags)
  1775. list(APPEND extra_target_args
  1776. BUNDLE_ID "com.rmsl.juceInAppPurchaseSample"
  1777. NEEDS_STORE_KIT TRUE)
  1778. endif()
  1779. if(pip_kind STREQUAL "AudioProcessor")
  1780. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in")
  1781. # We add AAX/VST2 targets too, if the user has set up those SDKs
  1782. set(extra_formats)
  1783. if(TARGET juce_aax_sdk)
  1784. list(APPEND extra_formats AAX)
  1785. endif()
  1786. if(TARGET juce_vst2_sdk)
  1787. list(APPEND extra_formats VST)
  1788. endif()
  1789. # Standalone plugins might want to access the mic
  1790. list(APPEND extra_target_args MICROPHONE_PERMISSION_ENABLED TRUE)
  1791. juce_add_plugin(${JUCE_PIP_NAME}
  1792. FORMATS AU AUv3 VST3 Unity Standalone ${extra_formats}
  1793. ${extra_target_args})
  1794. elseif(pip_kind STREQUAL "Component")
  1795. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPComponent.cpp.in")
  1796. juce_add_gui_app(${JUCE_PIP_NAME} ${extra_target_args})
  1797. elseif(pip_kind STREQUAL "Console")
  1798. set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPConsole.cpp.in")
  1799. juce_add_console_app(${JUCE_PIP_NAME} ${extra_target_args})
  1800. else()
  1801. message(FATAL_ERROR "Error in '${header}': PIP kind must be either AudioProcessor, Component, or Console")
  1802. endif()
  1803. if(NOT ARGV1 STREQUAL "")
  1804. set("${ARGV1}" "${JUCE_PIP_NAME}" PARENT_SCOPE)
  1805. endif()
  1806. # Generate Main.cpp
  1807. _juce_get_metadata("${metadata_dict}" mainClass JUCE_PIP_MAIN_CLASS)
  1808. get_target_property(juce_library_code ${JUCE_PIP_NAME} JUCE_GENERATED_SOURCES_DIRECTORY)
  1809. set(pip_main "${juce_library_code}/Main.cpp")
  1810. set(JUCE_PIP_HEADER "${header}")
  1811. configure_file(${source_main} ${pip_main})
  1812. target_sources(${JUCE_PIP_NAME} PRIVATE ${pip_main})
  1813. _juce_get_metadata("${metadata_dict}" dependencies pip_dependencies)
  1814. juce_generate_juce_header(${JUCE_PIP_NAME})
  1815. foreach(module IN LISTS pip_dependencies)
  1816. if(module STREQUAL "")
  1817. continue()
  1818. endif()
  1819. set(discovered_module)
  1820. if(TARGET "${module}")
  1821. set(discovered_module "${module}")
  1822. else()
  1823. message(FATAL_ERROR "Error in '${header}': No such module: ${module}")
  1824. endif()
  1825. target_link_libraries(${JUCE_PIP_NAME} PRIVATE ${discovered_module})
  1826. endforeach()
  1827. target_compile_definitions(${JUCE_PIP_NAME}
  1828. PRIVATE ${pip_moduleflags}
  1829. PUBLIC
  1830. JUCE_VST3_CAN_REPLACE_VST2=0)
  1831. _juce_get_pip_targets(${JUCE_PIP_NAME} pip_targets)
  1832. # This keeps the PIPs slightly better organised in the JUCE megaproject
  1833. if((DEFINED JUCE_SOURCE_DIR) AND (header MATCHES "^${JUCE_SOURCE_DIR}"))
  1834. file(RELATIVE_PATH folder "${JUCE_SOURCE_DIR}" "${header}")
  1835. get_filename_component(folder_parent "${folder}" DIRECTORY)
  1836. foreach(target_name IN ITEMS ${pip_targets} ${JUCE_PIP_NAME}_All)
  1837. if(TARGET "${target_name}")
  1838. set_target_properties("${target_name}" PROPERTIES
  1839. FOLDER "${folder_parent}/${JUCE_PIP_NAME}")
  1840. endif()
  1841. endforeach()
  1842. endif()
  1843. # We're building JUCE itself
  1844. if(DEFINED JUCE_SOURCE_DIR)
  1845. # PIPs need to know about the resources folder
  1846. target_compile_definitions(${JUCE_PIP_NAME} PRIVATE
  1847. PIP_JUCE_EXAMPLES_DIRECTORY_STRING="${JUCE_SOURCE_DIR}/examples")
  1848. get_filename_component(pip_parent_path "${header}" DIRECTORY)
  1849. target_include_directories(${JUCE_PIP_NAME} PRIVATE "${pip_parent_path}")
  1850. if((CMAKE_SYSTEM_NAME STREQUAL "iOS") AND (header MATCHES "^${JUCE_SOURCE_DIR}"))
  1851. foreach(target_name IN LISTS pip_targets)
  1852. if(TARGET "${target_name}")
  1853. juce_add_bundle_resources_directory("${target_name}" "${JUCE_SOURCE_DIR}/examples/Assets")
  1854. endif()
  1855. endforeach()
  1856. endif()
  1857. endif()
  1858. endfunction()
  1859. # ==================================================================================================
  1860. function(juce_set_aax_sdk_path path)
  1861. if(TARGET juce_aax_sdk)
  1862. message(FATAL_ERROR "juce_set_aax_sdk_path should only be called once")
  1863. endif()
  1864. _juce_make_absolute(path)
  1865. if((NOT EXISTS "${path}")
  1866. OR (NOT EXISTS "${path}/Interfaces")
  1867. OR (NOT EXISTS "${path}/Interfaces/ACF"))
  1868. message(FATAL_ERROR "Could not find AAX SDK at the specified path: ${path}")
  1869. endif()
  1870. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  1871. add_library(juce_aax_sdk STATIC IMPORTED GLOBAL)
  1872. set_target_properties(juce_aax_sdk PROPERTIES
  1873. IMPORTED_LOCATION_DEBUG "${path}/Libs/Debug/libAAXLibrary_libcpp.a"
  1874. IMPORTED_LOCATION "${path}/Libs/Release/libAAXLibrary_libcpp.a")
  1875. elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  1876. add_library(juce_aax_sdk INTERFACE IMPORTED GLOBAL)
  1877. else()
  1878. return()
  1879. endif()
  1880. target_include_directories(juce_aax_sdk INTERFACE
  1881. "${path}"
  1882. "${path}/Interfaces"
  1883. "${path}/Interfaces/ACF")
  1884. target_compile_definitions(juce_aax_sdk INTERFACE JucePlugin_AAXLibs_path="${path}/Libs")
  1885. set_target_properties(juce_aax_sdk PROPERTIES INTERFACE_JUCE_AAX_DEFAULT_ICON "${path}/Utilities/PlugIn.ico")
  1886. endfunction()
  1887. function(juce_set_vst2_sdk_path path)
  1888. if(TARGET juce_vst2_sdk)
  1889. message(FATAL_ERROR "juce_set_vst2_sdk_path should only be called once")
  1890. endif()
  1891. _juce_make_absolute(path)
  1892. if(NOT EXISTS "${path}")
  1893. message(FATAL_ERROR "Could not find VST2 SDK at the specified path: ${path}")
  1894. endif()
  1895. add_library(juce_vst2_sdk INTERFACE IMPORTED GLOBAL)
  1896. # This is a bit of a hack, but we really need the VST2 paths to always follow the VST3 paths.
  1897. target_include_directories(juce_vst2_sdk INTERFACE
  1898. $<TARGET_PROPERTY:juce::juce_vst3_headers,INTERFACE_INCLUDE_DIRECTORIES>
  1899. "${path}")
  1900. endfunction()
  1901. function(juce_set_vst3_sdk_path path)
  1902. if(TARGET juce_vst3_sdk)
  1903. message(FATAL_ERROR "juce_set_vst3_sdk_path should only be called once")
  1904. endif()
  1905. _juce_make_absolute(path)
  1906. if(NOT EXISTS "${path}")
  1907. message(FATAL_ERROR "Could not find VST3 SDK at the specified path: ${path}")
  1908. endif()
  1909. add_library(juce_vst3_sdk INTERFACE IMPORTED GLOBAL)
  1910. target_include_directories(juce_vst3_sdk INTERFACE "${path}")
  1911. endfunction()
  1912. # ==================================================================================================
  1913. function(juce_disable_default_flags)
  1914. set(langs C CXX)
  1915. set(modes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
  1916. foreach(lang IN LISTS langs)
  1917. foreach(mode IN LISTS modes)
  1918. list(FILTER CMAKE_${lang}_FLAGS_${mode} INCLUDE REGEX "[/-]M[TD]d?")
  1919. set(CMAKE_${lang}_FLAGS_${mode} "${CMAKE_${lang}_FLAGS_${mode}}" PARENT_SCOPE)
  1920. endforeach()
  1921. endforeach()
  1922. endfunction()