comparison DPF-Prymula-audioplugins/dpf/cmake/DPF-plugin.cmake @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 # DISTRHO Plugin Framework (DPF)
2 # Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
3 # Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
4 #
5 # SPDX-License-Identifier: ISC
6
7 # ------------------------------------------------------------------------------
8 # CMake support module for the DISTRHO Plugin Framework
9 #
10 # The purpose of this module is to help building music plugins easily, when the
11 # project uses CMake as its build system.
12 #
13 # In order to use the helpers provided by this module, a plugin author should
14 # add DPF as a subproject, making the function `dpf_add_plugin` available.
15 # The usage of this function is documented below in greater detail.
16 #
17 # Example project `CMakeLists.txt`:
18 #
19 # ```
20 # cmake_minimum_required(VERSION 3.7)
21 # project(MyPlugin)
22 #
23 # add_subdirectory(DPF)
24 #
25 # dpf_add_plugin(MyPlugin
26 # TARGETS clap lv2 vst2 vst3
27 # UI_TYPE opengl
28 # FILES_DSP
29 # src/MyPlugin.cpp
30 # FILES_UI
31 # src/MyUI.cpp)
32 #
33 # target_include_directories(MyPlugin
34 # PUBLIC src)
35 # ```
36 #
37 # Important: note that properties, such as include directories, definitions,
38 # and linked libraries *must* be marked with `PUBLIC` so they take effect and
39 # propagate into all the plugin targets.
40
41 include(CMakeParseArguments)
42
43 # ------------------------------------------------------------------------------
44 # DPF public functions
45 # ------------------------------------------------------------------------------
46
47 # dpf_add_plugin(name <args...>)
48 # ------------------------------------------------------------------------------
49 #
50 # Add a plugin built using the DISTRHO Plugin Framework.
51 #
52 # ------------------------------------------------------------------------------
53 # Created targets:
54 #
55 # `<name>`
56 # static library: the common part of the plugin
57 # The public properties set on this target apply to both DSP and UI.
58 #
59 # `<name>-dsp`
60 # static library: the DSP part of the plugin
61 # The public properties set on this target apply to the DSP only.
62 #
63 # `<name>-ui`
64 # static library: the UI part of the plugin
65 # The public properties set on this target apply to the UI only.
66 #
67 # `<name>-<target>` for each target specified with the `TARGETS` argument.
68 # This is target-dependent and not intended for public use.
69 #
70 # ------------------------------------------------------------------------------
71 # Arguments:
72 #
73 # `TARGETS` <tgt1>...<tgtN>
74 # a list of one of more of the following target types:
75 # `jack`, `ladspa`, `dssi`, `lv2`, `vst2`, `vst3`, `clap`
76 #
77 # `UI_TYPE` <type>
78 # the user interface type: `opengl` (default), `cairo`, `external`
79 #
80 # `FILES_COMMON` <file1>...<fileN>
81 # list of sources which are part of both DSP and UI
82 #
83 # `FILES_DSP` <file1>...<fileN>
84 # list of sources which are part of the DSP
85 #
86 # `FILES_UI` <file1>...<fileN>
87 # list of sources which are part of the UI
88 # empty indicates the plugin does not have UI
89 #
90 # `MODGUI_CLASS_NAME`
91 # class name to use for modgui builds
92 #
93 # `MONOLITHIC`
94 # build LV2 as a single binary for UI and DSP
95 #
96 # `NO_SHARED_RESOURCES`
97 # do not build DPF shared resources (fonts, etc)
98 #
99 function(dpf_add_plugin NAME)
100 set(options MONOLITHIC NO_SHARED_RESOURCES)
101 set(oneValueArgs MODGUI_CLASS_NAME UI_TYPE)
102 set(multiValueArgs FILES_COMMON FILES_DSP FILES_UI TARGETS)
103 cmake_parse_arguments(_dpf_plugin "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
104
105 if("${_dpf_plugin_UI_TYPE}" STREQUAL "")
106 set(_dpf_plugin_UI_TYPE "opengl")
107 endif()
108
109 set(_dgl_library)
110 set(_dgl_external OFF)
111 if(_dpf_plugin_FILES_UI)
112 if(_dpf_plugin_UI_TYPE STREQUAL "cairo")
113 dpf__add_dgl_cairo("${_dpf_plugin_NO_SHARED_RESOURCES}")
114 set(_dgl_library dgl-cairo)
115 elseif(_dpf_plugin_UI_TYPE STREQUAL "opengl")
116 dpf__add_dgl_opengl("${_dpf_plugin_NO_SHARED_RESOURCES}")
117 set(_dgl_library dgl-opengl)
118 elseif(_dpf_plugin_UI_TYPE STREQUAL "external")
119 set(_dgl_external ON)
120 else()
121 message(FATAL_ERROR "Unrecognized UI type for plugin: ${_dpf_plugin_UI_TYPE}")
122 endif()
123 endif()
124
125 set(_dgl_has_ui OFF)
126 if(_dgl_library OR _dgl_external)
127 set(_dgl_has_ui ON)
128 endif()
129
130 ###
131 dpf__ensure_sources_non_empty(_dpf_plugin_FILES_COMMON)
132 dpf__ensure_sources_non_empty(_dpf_plugin_FILES_DSP)
133 dpf__ensure_sources_non_empty(_dpf_plugin_FILES_UI)
134
135 ###
136 dpf__add_static_library("${NAME}" ${_dpf_plugin_FILES_COMMON})
137 target_include_directories("${NAME}" PUBLIC
138 "${DPF_ROOT_DIR}/distrho")
139
140 if(_dpf_plugin_MODGUI_CLASS_NAME)
141 target_compile_definitions("${NAME}" PUBLIC "DISTRHO_PLUGIN_MODGUI_CLASS_NAME=\"${_dpf_plugin_MODGUI_CLASS_NAME}\"")
142 endif()
143
144 if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
145 target_link_libraries("${NAME}" PRIVATE "dl")
146 endif()
147
148 if(_dgl_library AND NOT _dgl_external)
149 # make sure that all code will see DGL_* definitions
150 target_link_libraries("${NAME}" PUBLIC
151 "${_dgl_library}-definitions"
152 dgl-system-libs-definitions
153 dgl-system-libs)
154 endif()
155
156 dpf__add_static_library("${NAME}-dsp" ${_dpf_plugin_FILES_DSP})
157 target_link_libraries("${NAME}-dsp" PUBLIC "${NAME}")
158
159 if(_dgl_library AND NOT _dgl_external)
160 dpf__add_static_library("${NAME}-ui" ${_dpf_plugin_FILES_UI})
161 target_link_libraries("${NAME}-ui" PUBLIC "${NAME}" ${_dgl_library})
162 if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
163 target_link_libraries("${NAME}-ui" PRIVATE "dl")
164 endif()
165 # add the files containing Objective-C classes
166 dpf__add_plugin_specific_ui_sources("${NAME}-ui")
167 elseif(_dgl_external)
168 dpf__add_static_library("${NAME}-ui" ${_dpf_plugin_FILES_UI})
169 target_link_libraries("${NAME}-ui" PUBLIC "${NAME}")
170 if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
171 target_link_libraries("${NAME}-ui" PRIVATE "dl")
172 endif()
173 # add the files containing Objective-C classes
174 dpf__add_plugin_specific_ui_sources("${NAME}-ui")
175 else()
176 add_library("${NAME}-ui" INTERFACE)
177 endif()
178
179 ###
180 foreach(_target ${_dpf_plugin_TARGETS})
181 if(_target STREQUAL "jack")
182 dpf__build_jack("${NAME}" "${_dgl_has_ui}")
183 elseif(_target STREQUAL "ladspa")
184 dpf__build_ladspa("${NAME}")
185 elseif(_target STREQUAL "dssi")
186 dpf__build_dssi("${NAME}" "${_dgl_has_ui}")
187 elseif(_target STREQUAL "lv2")
188 dpf__build_lv2("${NAME}" "${_dgl_has_ui}" "${_dpf_plugin_MONOLITHIC}")
189 elseif(_target STREQUAL "vst2")
190 dpf__build_vst2("${NAME}" "${_dgl_has_ui}")
191 elseif(_target STREQUAL "vst3")
192 dpf__build_vst3("${NAME}" "${_dgl_has_ui}")
193 elseif(_target STREQUAL "clap")
194 dpf__build_clap("${NAME}" "${_dgl_has_ui}")
195 elseif(_target STREQUAL "static")
196 dpf__build_static("${NAME}" "${_dgl_has_ui}")
197 else()
198 message(FATAL_ERROR "Unrecognized target type for plugin: ${_target}")
199 endif()
200 endforeach()
201 endfunction()
202
203 # ------------------------------------------------------------------------------
204 # DPF private functions (prefixed with `dpf__`)
205 # ------------------------------------------------------------------------------
206
207 # Note: The $<0:> trick is to prevent MSVC from appending the build type
208 # to the output directory.
209 #
210
211 # dpf__build_jack
212 # ------------------------------------------------------------------------------
213 #
214 # Add build rules for a JACK/Standalone program.
215 #
216 function(dpf__build_jack NAME HAS_UI)
217 dpf__create_dummy_source_list(_no_srcs)
218
219 dpf__add_executable("${NAME}-jack" ${_no_srcs})
220 dpf__add_plugin_main("${NAME}-jack" "jack")
221 dpf__add_ui_main("${NAME}-jack" "jack" "${HAS_UI}")
222 target_link_libraries("${NAME}-jack" PRIVATE "${NAME}-dsp" "${NAME}-ui")
223 set_target_properties("${NAME}-jack" PROPERTIES
224 RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
225 OUTPUT_NAME "${NAME}")
226
227 target_compile_definitions("${NAME}" PUBLIC "HAVE_JACK")
228 target_compile_definitions("${NAME}-jack" PRIVATE "HAVE_GETTIMEOFDAY")
229
230 find_package(PkgConfig)
231 pkg_check_modules(SDL2 "sdl2")
232 if(SDL2_FOUND)
233 target_compile_definitions("${NAME}" PUBLIC "HAVE_SDL2")
234 target_include_directories("${NAME}-jack" PRIVATE ${SDL2_STATIC_INCLUDE_DIRS})
235 target_link_libraries("${NAME}-jack" PRIVATE ${SDL2_STATIC_LIBRARIES})
236 dpf__target_link_directories("${NAME}-jack" "${SDL2_STATIC_LIBRARY_DIRS}")
237 endif()
238
239 if(APPLE OR WIN32)
240 target_compile_definitions("${NAME}" PUBLIC "HAVE_RTAUDIO")
241 else()
242 find_package(Threads)
243 pkg_check_modules(ALSA "alsa")
244 pkg_check_modules(PULSEAUDIO "libpulse-simple")
245 if(ALSA_FOUND)
246 target_compile_definitions("${NAME}" PUBLIC "HAVE_ALSA")
247 target_include_directories("${NAME}-jack" PRIVATE ${ALSA_INCLUDE_DIRS})
248 target_link_libraries("${NAME}-jack" PRIVATE ${ALSA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
249 dpf__target_link_directories("${NAME}-jack" "${ALSA_LIBRARY_DIRS}")
250 endif()
251 if(PULSEAUDIO_FOUND)
252 target_compile_definitions("${NAME}" PUBLIC "HAVE_PULSEAUDIO")
253 target_include_directories("${NAME}-jack" PRIVATE ${PULSEAUDIO_INCLUDE_DIRS})
254 target_link_libraries("${NAME}-jack" PRIVATE ${PULSEAUDIO_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
255 dpf__target_link_directories("${NAME}-jack" "${PULSEAUDIO_LIBRARY_DIRS}")
256 endif()
257 if(ALSA_FOUND OR PULSEAUDIO_FOUND)
258 target_compile_definitions("${NAME}" PUBLIC "HAVE_RTAUDIO")
259 endif()
260 endif()
261
262 # for RtAudio native fallback
263 if(APPLE)
264 find_library(APPLE_COREAUDIO_FRAMEWORK "CoreAudio")
265 find_library(APPLE_COREFOUNDATION_FRAMEWORK "CoreFoundation")
266 find_library(APPLE_COREMIDI_FRAMEWORK "CoreMIDI")
267 target_link_libraries("${NAME}-jack" PRIVATE
268 "${APPLE_COREAUDIO_FRAMEWORK}"
269 "${APPLE_COREFOUNDATION_FRAMEWORK}"
270 "${APPLE_COREMIDI_FRAMEWORK}")
271 elseif(WIN32)
272 target_link_libraries("${NAME}-jack" PRIVATE "ksuser" "mfplat" "mfuuid" "ole32" "winmm" "wmcodecdspuuid")
273 if(HAS_UI AND MINGW)
274 set_target_properties("${NAME}-jack" PROPERTIES WIN32_EXECUTABLE TRUE)
275 endif()
276 endif()
277 endfunction()
278
279 # dpf__build_ladspa
280 # ------------------------------------------------------------------------------
281 #
282 # Add build rules for a LADSPA plugin.
283 #
284 function(dpf__build_ladspa NAME)
285 dpf__create_dummy_source_list(_no_srcs)
286
287 dpf__add_module("${NAME}-ladspa" ${_no_srcs})
288 dpf__add_plugin_main("${NAME}-ladspa" "ladspa")
289 dpf__set_module_export_list("${NAME}-ladspa" "ladspa")
290 target_link_libraries("${NAME}-ladspa" PRIVATE "${NAME}-dsp")
291 set_target_properties("${NAME}-ladspa" PROPERTIES
292 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
293 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/ladspa/$<0:>"
294 OUTPUT_NAME "${NAME}-ladspa"
295 PREFIX "")
296 endfunction()
297
298 # dpf__build_dssi
299 # ------------------------------------------------------------------------------
300 #
301 # Add build rules for a DSSI plugin.
302 #
303 function(dpf__build_dssi NAME HAS_UI)
304 find_package(PkgConfig)
305 pkg_check_modules(LIBLO "liblo")
306 if(NOT LIBLO_FOUND)
307 dpf__warn_once_only(missing_liblo
308 "liblo is not found, skipping the `dssi` plugin targets")
309 return()
310 endif()
311
312 dpf__create_dummy_source_list(_no_srcs)
313
314 dpf__add_module("${NAME}-dssi" ${_no_srcs})
315 dpf__add_plugin_main("${NAME}-dssi" "dssi")
316 dpf__set_module_export_list("${NAME}-dssi" "dssi")
317 target_link_libraries("${NAME}-dssi" PRIVATE "${NAME}-dsp")
318 set_target_properties("${NAME}-dssi" PROPERTIES
319 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
320 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/dssi/$<0:>"
321 OUTPUT_NAME "${NAME}-dssi"
322 PREFIX "")
323
324 if(HAS_UI)
325 dpf__add_executable("${NAME}-dssi-ui" ${_no_srcs})
326 dpf__add_ui_main("${NAME}-dssi-ui" "dssi" "${HAS_UI}")
327 target_link_libraries("${NAME}-dssi-ui" PRIVATE "${NAME}-ui")
328 set_target_properties("${NAME}-dssi-ui" PROPERTIES
329 RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}-dssi/$<0:>"
330 OUTPUT_NAME "${NAME}_ui")
331
332 target_compile_definitions("${NAME}" PUBLIC "HAVE_LIBLO")
333 target_include_directories("${NAME}-dssi-ui" PRIVATE ${LIBLO_INCLUDE_DIRS})
334 target_link_libraries("${NAME}-dssi-ui" PRIVATE ${LIBLO_LIBRARIES})
335 dpf__target_link_directories("${NAME}-dssi-ui" "${LIBLO_LIBRARY_DIRS}")
336 endif()
337 endfunction()
338
339 # dpf__build_lv2
340 # ------------------------------------------------------------------------------
341 #
342 # Add build rules for an LV2 plugin.
343 #
344 function(dpf__build_lv2 NAME HAS_UI MONOLITHIC)
345 dpf__create_dummy_source_list(_no_srcs)
346
347 dpf__add_module("${NAME}-lv2" ${_no_srcs})
348 dpf__add_plugin_main("${NAME}-lv2" "lv2")
349 if(HAS_UI AND MONOLITHIC)
350 dpf__set_module_export_list("${NAME}-lv2" "lv2")
351 else()
352 dpf__set_module_export_list("${NAME}-lv2" "lv2-dsp")
353 endif()
354 target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-dsp")
355 set_target_properties("${NAME}-lv2" PROPERTIES
356 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>"
357 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>"
358 OUTPUT_NAME "${NAME}_dsp"
359 PREFIX "")
360
361 if(HAS_UI)
362 if(MONOLITHIC)
363 dpf__add_ui_main("${NAME}-lv2" "lv2" "${HAS_UI}")
364 target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-ui")
365 set_target_properties("${NAME}-lv2" PROPERTIES
366 OUTPUT_NAME "${NAME}")
367 else()
368 dpf__add_module("${NAME}-lv2-ui" ${_no_srcs})
369 dpf__add_ui_main("${NAME}-lv2-ui" "lv2" "${HAS_UI}")
370 dpf__set_module_export_list("${NAME}-lv2-ui" "lv2-ui")
371 target_link_libraries("${NAME}-lv2-ui" PRIVATE "${NAME}-ui")
372 set_target_properties("${NAME}-lv2-ui" PROPERTIES
373 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>"
374 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>"
375 OUTPUT_NAME "${NAME}_ui"
376 PREFIX "")
377 endif()
378 endif()
379
380 dpf__add_lv2_ttl_generator()
381 add_dependencies("${NAME}-lv2" lv2_ttl_generator)
382
383 add_custom_command(TARGET "${NAME}-lv2" POST_BUILD
384 COMMAND
385 ${CMAKE_CROSSCOMPILING_EMULATOR}
386 "$<TARGET_FILE:lv2_ttl_generator>"
387 "$<TARGET_FILE:${NAME}-lv2>"
388 WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2"
389 DEPENDS lv2_ttl_generator)
390 endfunction()
391
392 # dpf__build_vst2
393 # ------------------------------------------------------------------------------
394 #
395 # Add build rules for a VST2 plugin.
396 #
397 function(dpf__build_vst2 NAME HAS_UI)
398 dpf__create_dummy_source_list(_no_srcs)
399
400 dpf__add_module("${NAME}-vst2" ${_no_srcs})
401 dpf__add_plugin_main("${NAME}-vst2" "vst2")
402 dpf__add_ui_main("${NAME}-vst2" "vst2" "${HAS_UI}")
403 dpf__set_module_export_list("${NAME}-vst2" "vst2")
404 target_link_libraries("${NAME}-vst2" PRIVATE "${NAME}-dsp" "${NAME}-ui")
405 set_target_properties("${NAME}-vst2" PROPERTIES
406 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
407 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst2/$<0:>"
408 OUTPUT_NAME "${NAME}-vst2"
409 PREFIX "")
410 if(APPLE)
411 set_target_properties("${NAME}-vst2" PROPERTIES
412 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents/MacOS/$<0:>"
413 OUTPUT_NAME "${NAME}"
414 SUFFIX "")
415 set(INFO_PLIST_PROJECT_NAME "${NAME}")
416 configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist"
417 "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents/Info.plist" @ONLY)
418 file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo"
419 DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents")
420 endif()
421 endfunction()
422
423 # dpf__determine_vst3_package_architecture
424 # ------------------------------------------------------------------------------
425 #
426 # Determines the package architecture for a VST3 plugin target.
427 #
428 function(dpf__determine_vst3_package_architecture OUTPUT_VARIABLE)
429 # if set by variable, override the detection
430 if(DPF_VST3_ARCHITECTURE)
431 set("${OUTPUT_VARIABLE}" "${DPF_VST3_ARCHITECTURE}" PARENT_SCOPE)
432 return()
433 endif()
434
435 # not used on Apple, which supports universal binary
436 if(APPLE)
437 set("${OUTPUT_VARIABLE}" "universal" PARENT_SCOPE)
438 return()
439 endif()
440
441 # identify the target processor (special case of MSVC, problematic sometimes)
442 if(MSVC)
443 set(vst3_system_arch "${MSVC_CXX_ARCHITECTURE_ID}")
444 else()
445 set(vst3_system_arch "${CMAKE_SYSTEM_PROCESSOR}")
446 endif()
447
448 # transform the processor name to a format that VST3 recognizes
449 if(vst3_system_arch MATCHES "^(x86_64|amd64|AMD64|x64|X64)$")
450 set(vst3_package_arch "x86_64")
451 elseif(vst3_system_arch MATCHES "^(i.86|x86|X86)$")
452 if(WIN32)
453 set(vst3_package_arch "x86")
454 else()
455 set(vst3_package_arch "i386")
456 endif()
457 elseif(vst3_system_arch MATCHES "^(armv[3-8][a-z]*)$")
458 set(vst3_package_arch "${vst3_system_arch}")
459 elseif(vst3_system_arch MATCHES "^(aarch64)$")
460 set(vst3_package_arch "aarch64")
461 else()
462 message(FATAL_ERROR "We don't know this architecture for VST3: ${vst3_system_arch}.")
463 endif()
464
465 # TODO: the detections for Windows arm/arm64 when supported
466
467 set("${OUTPUT_VARIABLE}" "${vst3_package_arch}" PARENT_SCOPE)
468 endfunction()
469
470 # dpf__build_vst3
471 # ------------------------------------------------------------------------------
472 #
473 # Add build rules for a VST3 plugin.
474 #
475 function(dpf__build_vst3 NAME HAS_UI)
476 dpf__determine_vst3_package_architecture(vst3_arch)
477
478 dpf__create_dummy_source_list(_no_srcs)
479
480 dpf__add_module("${NAME}-vst3" ${_no_srcs})
481 dpf__add_plugin_main("${NAME}-vst3" "vst3")
482 dpf__add_ui_main("${NAME}-vst3" "vst3" "${HAS_UI}")
483 dpf__set_module_export_list("${NAME}-vst3" "vst3")
484 target_link_libraries("${NAME}-vst3" PRIVATE "${NAME}-dsp" "${NAME}-ui")
485 set_target_properties("${NAME}-vst3" PROPERTIES
486 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst3/$<0:>"
487 OUTPUT_NAME "${NAME}"
488 PREFIX "")
489
490 if(APPLE)
491 set_target_properties("${NAME}-vst3" PROPERTIES
492 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/MacOS/$<0:>"
493 SUFFIX "")
494 elseif(WIN32)
495 set_target_properties("${NAME}-vst3" PROPERTIES
496 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-win/$<0:>" SUFFIX ".vst3")
497 else()
498 set_target_properties("${NAME}-vst3" PROPERTIES
499 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-linux/$<0:>")
500 endif()
501
502 if(APPLE)
503 # Uses the same macOS bundle template as VST2
504 set(INFO_PLIST_PROJECT_NAME "${NAME}")
505 configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist"
506 "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/Info.plist" @ONLY)
507 file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo"
508 DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents")
509 endif()
510 endfunction()
511
512 # dpf__build_clap
513 # ------------------------------------------------------------------------------
514 #
515 # Add build rules for a CLAP plugin.
516 #
517 function(dpf__build_clap NAME HAS_UI)
518 dpf__create_dummy_source_list(_no_srcs)
519
520 dpf__add_module("${NAME}-clap" ${_no_srcs})
521 dpf__add_plugin_main("${NAME}-clap" "clap")
522 dpf__add_ui_main("${NAME}-clap" "clap" "${HAS_UI}")
523 dpf__set_module_export_list("${NAME}-clap" "clap")
524 target_link_libraries("${NAME}-clap" PRIVATE "${NAME}-dsp" "${NAME}-ui")
525 set_target_properties("${NAME}-clap" PROPERTIES
526 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
527 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/clap/$<0:>"
528 OUTPUT_NAME "${NAME}"
529 PREFIX ""
530 SUFFIX ".clap")
531
532 if(APPLE)
533 set_target_properties("${NAME}-clap" PROPERTIES
534 LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents/MacOS/$<0:>"
535 OUTPUT_NAME "${NAME}"
536 SUFFIX "")
537 set(INFO_PLIST_PROJECT_NAME "${NAME}")
538 configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist"
539 "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents/Info.plist" @ONLY)
540 file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo"
541 DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents")
542 endif()
543 endfunction()
544
545 # dpf__build_static
546 # ------------------------------------------------------------------------------
547 #
548 # Add build rules for a static library.
549 #
550 function(dpf__build_static NAME HAS_UI)
551 dpf__create_dummy_source_list(_no_srcs)
552
553 dpf__add_module("${NAME}-static" ${_no_srcs} STATIC)
554 dpf__add_plugin_main("${NAME}-static" "static")
555 dpf__add_ui_main("${NAME}-static" "static" "${HAS_UI}")
556 target_link_libraries("${NAME}-static" PRIVATE "${NAME}-dsp" "${NAME}-ui")
557
558 get_target_property(dsp_srcs "${NAME}-dsp" SOURCES)
559 get_target_property(ui_srcs "${NAME}-ui" SOURCES)
560 foreach(src ${dsp_srcs})
561 target_sources("${NAME}-static" PRIVATE ${src})
562 endforeach()
563 foreach(src ${ui_srcs})
564 target_sources("${NAME}-static" PRIVATE ${src})
565 endforeach()
566
567 set_target_properties("${NAME}-static" PROPERTIES
568 ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>"
569 OUTPUT_NAME "${NAME}"
570 PREFIX "")
571 endfunction()
572
573 # dpf__add_dgl_cairo
574 # ------------------------------------------------------------------------------
575 #
576 # Add the Cairo variant of DGL, if not already available.
577 #
578 function(dpf__add_dgl_cairo NO_SHARED_RESOURCES)
579 if(TARGET dgl-cairo)
580 return()
581 endif()
582
583 find_package(PkgConfig)
584 pkg_check_modules(CAIRO "cairo" REQUIRED)
585
586 link_directories(${CAIRO_LIBRARY_DIRS})
587
588 dpf__add_static_library(dgl-cairo STATIC
589 "${DPF_ROOT_DIR}/dgl/src/Application.cpp"
590 "${DPF_ROOT_DIR}/dgl/src/ApplicationPrivateData.cpp"
591 "${DPF_ROOT_DIR}/dgl/src/Color.cpp"
592 "${DPF_ROOT_DIR}/dgl/src/EventHandlers.cpp"
593 "${DPF_ROOT_DIR}/dgl/src/Geometry.cpp"
594 "${DPF_ROOT_DIR}/dgl/src/ImageBase.cpp"
595 "${DPF_ROOT_DIR}/dgl/src/ImageBaseWidgets.cpp"
596 "${DPF_ROOT_DIR}/dgl/src/Layout.cpp"
597 "${DPF_ROOT_DIR}/dgl/src/SubWidget.cpp"
598 "${DPF_ROOT_DIR}/dgl/src/SubWidgetPrivateData.cpp"
599 "${DPF_ROOT_DIR}/dgl/src/TopLevelWidget.cpp"
600 "${DPF_ROOT_DIR}/dgl/src/TopLevelWidgetPrivateData.cpp"
601 "${DPF_ROOT_DIR}/dgl/src/Widget.cpp"
602 "${DPF_ROOT_DIR}/dgl/src/WidgetPrivateData.cpp"
603 "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
604 "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
605 "${DPF_ROOT_DIR}/dgl/src/Cairo.cpp")
606 if(NO_SHARED_RESOURCES)
607 target_compile_definitions(dgl-cairo PUBLIC "DGL_NO_SHARED_RESOURCES")
608 else()
609 target_sources(dgl-cairo PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")
610 endif()
611 if(NOT APPLE)
612 target_sources(dgl-cairo PRIVATE
613 "${DPF_ROOT_DIR}/dgl/src/pugl.cpp")
614 else()
615 target_sources(dgl-cairo PRIVATE
616 "${DPF_ROOT_DIR}/dgl/src/pugl.mm")
617 endif()
618 target_include_directories(dgl-cairo PUBLIC
619 "${DPF_ROOT_DIR}/dgl")
620 target_include_directories(dgl-cairo PUBLIC
621 "${DPF_ROOT_DIR}/dgl/src/pugl-upstream/include")
622
623 dpf__add_dgl_system_libs()
624 target_link_libraries(dgl-cairo PRIVATE dgl-system-libs)
625
626 add_library(dgl-cairo-definitions INTERFACE)
627 target_compile_definitions(dgl-cairo-definitions INTERFACE "DGL_CAIRO" "HAVE_CAIRO" "HAVE_DGL")
628
629 target_include_directories(dgl-cairo PUBLIC ${CAIRO_INCLUDE_DIRS})
630 if(MINGW)
631 target_link_libraries(dgl-cairo PRIVATE ${CAIRO_STATIC_LIBRARIES})
632 else()
633 target_link_libraries(dgl-cairo PRIVATE ${CAIRO_LIBRARIES})
634 endif()
635 target_link_libraries(dgl-cairo PRIVATE dgl-cairo-definitions)
636 endfunction()
637
638 # dpf__add_dgl_opengl
639 # ------------------------------------------------------------------------------
640 #
641 # Add the OpenGL variant of DGL, if not already available.
642 #
643 function(dpf__add_dgl_opengl NO_SHARED_RESOURCES)
644 if(TARGET dgl-opengl)
645 return()
646 endif()
647
648 if(NOT OpenGL_GL_PREFERENCE)
649 set(OpenGL_GL_PREFERENCE "LEGACY")
650 endif()
651
652 find_package(OpenGL REQUIRED)
653
654 dpf__add_static_library(dgl-opengl STATIC
655 "${DPF_ROOT_DIR}/dgl/src/Application.cpp"
656 "${DPF_ROOT_DIR}/dgl/src/ApplicationPrivateData.cpp"
657 "${DPF_ROOT_DIR}/dgl/src/Color.cpp"
658 "${DPF_ROOT_DIR}/dgl/src/EventHandlers.cpp"
659 "${DPF_ROOT_DIR}/dgl/src/Geometry.cpp"
660 "${DPF_ROOT_DIR}/dgl/src/ImageBase.cpp"
661 "${DPF_ROOT_DIR}/dgl/src/ImageBaseWidgets.cpp"
662 "${DPF_ROOT_DIR}/dgl/src/Layout.cpp"
663 "${DPF_ROOT_DIR}/dgl/src/SubWidget.cpp"
664 "${DPF_ROOT_DIR}/dgl/src/SubWidgetPrivateData.cpp"
665 "${DPF_ROOT_DIR}/dgl/src/TopLevelWidget.cpp"
666 "${DPF_ROOT_DIR}/dgl/src/TopLevelWidgetPrivateData.cpp"
667 "${DPF_ROOT_DIR}/dgl/src/Widget.cpp"
668 "${DPF_ROOT_DIR}/dgl/src/WidgetPrivateData.cpp"
669 "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
670 "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
671 "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp"
672 "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp")
673 if(NO_SHARED_RESOURCES)
674 target_compile_definitions(dgl-opengl PUBLIC "DGL_NO_SHARED_RESOURCES")
675 else()
676 target_sources(dgl-opengl PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")
677 endif()
678 if(NOT APPLE)
679 target_sources(dgl-opengl PRIVATE
680 "${DPF_ROOT_DIR}/dgl/src/pugl.cpp")
681 else()
682 target_sources(dgl-opengl PRIVATE
683 "${DPF_ROOT_DIR}/dgl/src/pugl.mm")
684 endif()
685 target_include_directories(dgl-opengl PUBLIC
686 "${DPF_ROOT_DIR}/dgl")
687 target_include_directories(dgl-opengl PUBLIC
688 "${DPF_ROOT_DIR}/dgl/src/pugl-upstream/include")
689
690 if(APPLE)
691 target_compile_definitions(dgl-opengl PUBLIC "GL_SILENCE_DEPRECATION")
692 endif()
693
694 dpf__add_dgl_system_libs()
695 target_link_libraries(dgl-opengl PRIVATE dgl-system-libs)
696
697 add_library(dgl-opengl-definitions INTERFACE)
698 target_compile_definitions(dgl-opengl-definitions INTERFACE "DGL_OPENGL" "HAVE_OPENGL" "HAVE_DGL")
699
700 target_include_directories(dgl-opengl PUBLIC "${OPENGL_INCLUDE_DIR}")
701 target_link_libraries(dgl-opengl PRIVATE dgl-opengl-definitions "${OPENGL_gl_LIBRARY}")
702 endfunction()
703
704 # dpf__add_plugin_specific_ui_sources
705 # ------------------------------------------------------------------------------
706 #
707 # Compile system specific files, for now it is just Objective-C code
708 #
709 function(dpf__add_plugin_specific_ui_sources NAME)
710 if(APPLE)
711 target_sources("${NAME}" PRIVATE
712 "${DPF_ROOT_DIR}/distrho/DistrhoUI_macOS.mm")
713 endif()
714 endfunction()
715
716 # dpf__add_dgl_system_libs
717 # ------------------------------------------------------------------------------
718 #
719 # Find system libraries required by DGL and add them as an interface target.
720 #
721 function(dpf__add_dgl_system_libs)
722 if(TARGET dgl-system-libs)
723 return()
724 endif()
725 add_library(dgl-system-libs INTERFACE)
726 add_library(dgl-system-libs-definitions INTERFACE)
727 if(APPLE)
728 find_library(APPLE_COCOA_FRAMEWORK "Cocoa")
729 find_library(APPLE_COREVIDEO_FRAMEWORK "CoreVideo")
730 target_link_libraries(dgl-system-libs INTERFACE "${APPLE_COCOA_FRAMEWORK}" "${APPLE_COREVIDEO_FRAMEWORK}")
731 elseif(EMSCRIPTEN)
732 elseif(HAIKU)
733 target_link_libraries(dgl-system-libs INTERFACE "be")
734 elseif(WIN32)
735 target_link_libraries(dgl-system-libs INTERFACE "gdi32" "comdlg32")
736 else()
737 find_package(PkgConfig)
738 pkg_check_modules(DBUS "dbus-1")
739 if(DBUS_FOUND)
740 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_DBUS")
741 target_include_directories(dgl-system-libs INTERFACE "${DBUS_INCLUDE_DIRS}")
742 target_link_libraries(dgl-system-libs INTERFACE "${DBUS_LIBRARIES}")
743 endif()
744 find_package(X11 REQUIRED)
745 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_X11")
746 target_include_directories(dgl-system-libs INTERFACE "${X11_INCLUDE_DIR}")
747 target_link_libraries(dgl-system-libs INTERFACE "${X11_X11_LIB}")
748 if(X11_Xcursor_FOUND)
749 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XCURSOR")
750 target_link_libraries(dgl-system-libs INTERFACE "${X11_Xcursor_LIB}")
751 endif()
752 if(X11_Xext_FOUND)
753 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XEXT")
754 target_link_libraries(dgl-system-libs INTERFACE "${X11_Xext_LIB}")
755 endif()
756 if(X11_Xrandr_FOUND)
757 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XRANDR")
758 target_link_libraries(dgl-system-libs INTERFACE "${X11_Xrandr_LIB}")
759 endif()
760 if(X11_XSync_FOUND)
761 target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XSYNC")
762 target_link_libraries(dgl-system-libs INTERFACE "${X11_XSync_LIB}")
763 endif()
764 endif()
765
766 if(MSVC)
767 file(MAKE_DIRECTORY "${DPF_ROOT_DIR}/khronos/GL")
768 foreach(_gl_header "glext.h")
769 if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}")
770 file(DOWNLOAD "https://www.khronos.org/registry/OpenGL/api/GL/${_gl_header}" "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}" SHOW_PROGRESS)
771 endif()
772 endforeach()
773 foreach(_khr_header "khrplatform.h")
774 if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}")
775 file(DOWNLOAD "https://www.khronos.org/registry/EGL/api/KHR/${_khr_header}" "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}" SHOW_PROGRESS)
776 endif()
777 endforeach()
778 target_include_directories(dgl-system-libs-definitions INTERFACE "${DPF_ROOT_DIR}/khronos")
779 endif()
780
781 target_link_libraries(dgl-system-libs INTERFACE dgl-system-libs-definitions)
782 endfunction()
783
784 # dpf__add_executable
785 # ------------------------------------------------------------------------------
786 #
787 # Adds an executable target, and set some default properties on the target.
788 #
789 function(dpf__add_executable NAME)
790 add_executable("${NAME}" ${ARGN})
791 dpf__set_target_defaults("${NAME}")
792 if(MINGW)
793 target_link_libraries("${NAME}" PRIVATE "-static")
794 endif()
795 endfunction()
796
797 # dpf__add_module
798 # ------------------------------------------------------------------------------
799 #
800 # Adds a module target, and set some default properties on the target.
801 #
802 function(dpf__add_module NAME)
803 add_library("${NAME}" MODULE ${ARGN})
804 dpf__set_target_defaults("${NAME}")
805 if(MINGW)
806 target_link_libraries("${NAME}" PRIVATE "-static")
807 endif()
808 endfunction()
809
810 # dpf__add_static_library
811 # ------------------------------------------------------------------------------
812 #
813 # Adds a static library target, and set some default properties on the target.
814 #
815 function(dpf__add_static_library NAME)
816 add_library("${NAME}" STATIC ${ARGN})
817 dpf__set_target_defaults("${NAME}")
818 endfunction()
819
820 # dpf__set_module_export_list
821 # ------------------------------------------------------------------------------
822 #
823 # Applies a list of exported symbols to the module target.
824 #
825 function(dpf__set_module_export_list NAME EXPORTS)
826 if(WIN32)
827 target_sources("${NAME}" PRIVATE "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.def")
828 elseif(APPLE)
829 set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS
830 "-Xlinker" "-exported_symbols_list"
831 "-Xlinker" "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.exp")
832 else()
833 set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS
834 "-Xlinker" "--version-script=${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.version")
835 endif()
836 endfunction()
837
838 # dpf__set_target_defaults
839 # ------------------------------------------------------------------------------
840 #
841 # Set default properties which must apply to all DPF-defined targets.
842 #
843 function(dpf__set_target_defaults NAME)
844 set_target_properties("${NAME}" PROPERTIES
845 POSITION_INDEPENDENT_CODE TRUE
846 C_VISIBILITY_PRESET "hidden"
847 CXX_VISIBILITY_PRESET "hidden"
848 VISIBILITY_INLINES_HIDDEN TRUE)
849 if(WIN32)
850 target_compile_definitions("${NAME}" PUBLIC "NOMINMAX")
851 endif()
852 if (MINGW)
853 target_compile_options("${NAME}" PUBLIC "-mstackrealign")
854 endif()
855 if (MSVC)
856 target_compile_options("${NAME}" PUBLIC "/UTF-8")
857 target_compile_definitions("${NAME}" PUBLIC "_CRT_SECURE_NO_WARNINGS")
858 endif()
859 if (CMAKE_COMPILER_IS_GNUCXX)
860 target_compile_options("${NAME}" PUBLIC "-fno-gnu-unique")
861 endif()
862 endfunction()
863
864 # dpf__add_plugin_main
865 # ------------------------------------------------------------------------------
866 #
867 # Adds plugin code to the given target.
868 #
869 function(dpf__add_plugin_main NAME TARGET)
870 target_sources("${NAME}" PRIVATE
871 "${DPF_ROOT_DIR}/distrho/DistrhoPluginMain.cpp")
872 dpf__add_plugin_target_definition("${NAME}" "${TARGET}")
873 endfunction()
874
875 # dpf__add_ui_main
876 # ------------------------------------------------------------------------------
877 #
878 # Adds UI code to the given target (only if the target has UI).
879 #
880 function(dpf__add_ui_main NAME TARGET HAS_UI)
881 if(HAS_UI)
882 target_sources("${NAME}" PRIVATE
883 "${DPF_ROOT_DIR}/distrho/DistrhoUIMain.cpp")
884 dpf__add_plugin_target_definition("${NAME}" "${TARGET}")
885 endif()
886 endfunction()
887
888 # dpf__add_plugin_target_definition
889 # ------------------------------------------------------------------------------
890 #
891 # Adds the plugins target macro definition.
892 # This selects which entry file is compiled according to the target type.
893 #
894 function(dpf__add_plugin_target_definition NAME TARGET)
895 string(TOUPPER "${TARGET}" _upperTarget)
896 target_compile_definitions("${NAME}" PRIVATE "DISTRHO_PLUGIN_TARGET_${_upperTarget}")
897 endfunction()
898
899 # dpf__add_lv2_ttl_generator
900 # ------------------------------------------------------------------------------
901 #
902 # Build the LV2 TTL generator.
903 #
904 function(dpf__add_lv2_ttl_generator)
905 if(TARGET lv2_ttl_generator)
906 return()
907 endif()
908 add_executable(lv2_ttl_generator "${DPF_ROOT_DIR}/utils/lv2-ttl-generator/lv2_ttl_generator.c")
909 if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU))
910 target_link_libraries(lv2_ttl_generator PRIVATE "dl")
911 endif()
912 endfunction()
913
914 # dpf__ensure_sources_non_empty
915 # ------------------------------------------------------------------------------
916 #
917 # Ensure the given source list contains at least one file.
918 # The function appends an empty source file to the list if necessary.
919 # This is useful when CMake does not permit to add targets without sources.
920 #
921 function(dpf__ensure_sources_non_empty VAR)
922 if(NOT "" STREQUAL "${${VAR}}")
923 return()
924 endif()
925 set(_file "${CMAKE_CURRENT_BINARY_DIR}/_dpf_empty.c")
926 if(NOT EXISTS "${_file}")
927 file(WRITE "${_file}" "")
928 endif()
929 set("${VAR}" "${_file}" PARENT_SCOPE)
930 endfunction()
931
932 # dpf__create_dummy_source_list
933 # ------------------------------------------------------------------------------
934 #
935 # Create a dummy source list which is equivalent to compiling nothing.
936 # This is only for compatibility with older CMake versions, which refuse to add
937 # targets without any sources.
938 #
939 macro(dpf__create_dummy_source_list VAR)
940 set("${VAR}")
941 if(CMAKE_VERSION VERSION_LESS "3.11")
942 dpf__ensure_sources_non_empty("${VAR}")
943 endif()
944 endmacro()
945
946 # dpf__target_link_directories
947 # ------------------------------------------------------------------------------
948 #
949 # Call `target_link_directories` if cmake >= 3.13,
950 # otherwise fallback to global `link_directories`.
951 #
952 macro(dpf__target_link_directories NAME DIRS)
953 if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.13")
954 target_link_directories("${NAME}" PUBLIC ${DIRS})
955 else()
956 link_directories(${DIRS})
957 endif()
958 endmacro()
959
960 # dpf__warn_once
961 # ------------------------------------------------------------------------------
962 #
963 # Prints a warning message once only.
964 #
965 function(dpf__warn_once_only TOKEN MESSAGE)
966 get_property(_warned GLOBAL PROPERTY "dpf__have_warned_${TOKEN}")
967 if(NOT _warned)
968 set_property(GLOBAL PROPERTY "dpf__have_warned_${TOKEN}" TRUE)
969 message(WARNING "${MESSAGE}")
970 endif()
971 endfunction()