CMakeLists.txt 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. cmake_minimum_required(VERSION 2.8.12)
  2. cmake_policy(SET CMP0077 NEW)
  3. project(bell)
  4. # Configurable options
  5. option(BELL_DISABLE_CODECS "Disable the entire audio codec wrapper" OFF)
  6. option(BELL_CODEC_AAC "Support libhelix-aac codec" ON)
  7. option(BELL_CODEC_MP3 "Support libhelix-mp3 codec" ON)
  8. option(BELL_DISABLE_MQTT "Disable the built-in MQTT wrapper" OFF)
  9. option(BELL_CODEC_VORBIS "Support tremor Vorbis codec" ON)
  10. option(BELL_CODEC_ALAC "Support Apple ALAC codec" ON)
  11. option(BELL_CODEC_OPUS "Support Opus codec" ON)
  12. option(BELL_DISABLE_SINKS "Disable all built-in audio sink implementations" OFF)
  13. # These are default OFF, as they're OS-dependent (ESP32 sinks are always enabled - no external deps)
  14. option(BELL_SINK_ALSA "Enable ALSA audio sink" OFF)
  15. option(BELL_SINK_PORTAUDIO "Enable PortAudio sink" OFF)
  16. # cJSON wrapper
  17. option(BELL_ONLY_CJSON "Use only cJSON, not Nlohmann")
  18. set(BELL_EXTERNAL_CJSON "" CACHE STRING "External cJSON library target name, optional")
  19. # vorbis
  20. set(BELL_EXTERNAL_VORBIS "" CACHE STRING "External Vorbis library target name, optional")
  21. option(BELL_VORBIS_FLOAT "Use floating point Vorbis API" OFF)
  22. # fmt & regex
  23. option(BELL_DISABLE_FMT "Don't use std::fmt (saves space)" OFF)
  24. option(BELL_DISABLE_REGEX "Don't use std::regex (saves space)" OFF)
  25. # disable json tests
  26. set(JSON_BuildTests OFF CACHE INTERNAL "")
  27. # Backwards compatibility with deprecated options
  28. if(BELL_USE_ALSA)
  29. message(WARNING "Deprecated Bell options used, replace BELL_USE_ALSA with BELL_SINK_ALSA")
  30. set(BELL_SINK_ALSA ${BELL_USE_ALSA})
  31. endif()
  32. if(BELL_USE_PORTAUDIO)
  33. message(WARNING "Deprecated Bell options used, replace BELL_USE_PORTAUDIO with BELL_SINK_PORTAUDIO")
  34. set(BELL_SINK_PORTAUDIO ${BELL_USE_PORTAUDIO})
  35. endif()
  36. message(STATUS "Bell options:")
  37. message(STATUS " Disable all codecs: ${BELL_DISABLE_CODECS}")
  38. if(NOT BELL_DISABLE_CODECS)
  39. message(STATUS " - AAC audio codec: ${BELL_CODEC_AAC}")
  40. message(STATUS " - MP3 audio codec: ${BELL_CODEC_MP3}")
  41. message(STATUS " - Vorbis audio codec: ${BELL_CODEC_VORBIS}")
  42. message(STATUS " - Opus audio codec: ${BELL_CODEC_OPUS}")
  43. message(STATUS " - ALAC audio codec: ${BELL_CODEC_ALAC}")
  44. endif()
  45. message(STATUS " Disable built-in audio sinks: ${BELL_DISABLE_SINKS}")
  46. message(STATUS " Use Vorbis float version: ${BELL_VORBIS_FLOAT}")
  47. if(NOT BELL_DISABLE_SINKS)
  48. message(STATUS " - ALSA sink: ${BELL_SINK_ALSA}")
  49. message(STATUS " - PortAudio sink: ${BELL_SINK_PORTAUDIO}")
  50. endif()
  51. message(STATUS " Use cJSON only: ${BELL_ONLY_CJSON}")
  52. message(STATUS " Disable Fmt: ${BELL_DISABLE_FMT}")
  53. message(STATUS " Disable Mqtt: ${BELL_DISABLE_MQTT}")
  54. message(STATUS " Disable Regex: ${BELL_DISABLE_REGEX}")
  55. # Include nanoPB library
  56. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb/extra")
  57. find_package(Nanopb REQUIRED)
  58. message(${NANOPB_INCLUDE_DIRS})
  59. list(APPEND EXTERNAL_INCLUDES ${NANOPB_INCLUDE_DIRS})
  60. # CMake options
  61. set(CMAKE_CXX_STANDARD 20)
  62. set(CMAKE_CXX_STANDARD_REQUIRED 20)
  63. set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
  64. set(AUDIO_CODEC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-codec")
  65. set(AUDIO_CONTAINERS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-containers")
  66. set(AUDIO_DSP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-dsp")
  67. set(AUDIO_SINKS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/audio-sinks")
  68. set(IO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/io")
  69. set(PLATFORM_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/platform")
  70. set(UTILITIES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/main/utilities")
  71. add_definitions("-DUSE_DEFAULT_STDLIB=1 -DTARGET_OS_IPHONE=0")
  72. # Main library sources
  73. file(GLOB SOURCES
  74. "external/nanopb/*.c"
  75. "main/utilities/*.cpp" "main/utilities/*.c"
  76. "main/io/*.cpp" "main/io/*.c"
  77. )
  78. list(REMOVE_ITEM SOURCES "${IO_DIR}/BellTar.cpp" "${IO_DIR}/BellHTTPServer.cpp")
  79. list(APPEND EXTRA_INCLUDES "main/audio-codec/include")
  80. list(APPEND EXTRA_INCLUDES "main/audio-dsp/include")
  81. list(APPEND EXTRA_INCLUDES "main/audio-sinks/include")
  82. list(APPEND EXTRA_INCLUDES "main/io/include")
  83. list(APPEND EXTRA_INCLUDES "main/utilities/include")
  84. list(APPEND EXTRA_INCLUDES "main/platform")
  85. # Add platform specific sources
  86. if(ESP_PLATFORM)
  87. file(GLOB ESP_PLATFORM_SOURCES "main/platform/esp/*.cpp" "main/platform/esp/*.c" "main/asm/biquad_f32_ae32.S")
  88. list(APPEND SOURCES ${ESP_PLATFORM_SOURCES})
  89. endif()
  90. if(APPLE)
  91. file(GLOB APPLE_PLATFORM_SOURCES "main/platform/apple/*.cpp" "main/platform/apple/*.c")
  92. list(APPEND SOURCES ${APPLE_PLATFORM_SOURCES})
  93. list(APPEND EXTERNAL_INCLUDES "/usr/local/opt/mbedtls@3/include")
  94. endif()
  95. if(UNIX AND NOT APPLE)
  96. file(GLOB LINUX_PLATFORM_SOURCES "main/platform/linux/*.cpp" "main/platform/linux/*.c")
  97. list(APPEND SOURCES ${LINUX_PLATFORM_SOURCES})
  98. endif()
  99. if(WIN32)
  100. file(GLOB WIN32_PLATFORM_SOURCES "main/platform/win32/*.cpp" "main/platform/win32/*.c")
  101. list(APPEND SOURCES ${WIN32_PLATFORM_SOURCES})
  102. list(APPEND EXTERNAL_INCLUDES "main/platform/win32")
  103. endif()
  104. # A hack to make Opus keep quiet
  105. function(message)
  106. if(NOT MESSAGE_QUIET)
  107. _message(${ARGN})
  108. endif()
  109. endfunction()
  110. if(ESP_PLATFORM)
  111. list(APPEND EXTRA_LIBS idf::mdns idf::mbedtls idf::pthread idf::driver idf::lwip)
  112. add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation -Wno-stringop-overflow -Wno-error=format -Wno-format -Wno-stringop-overread -Wno-stringop-overflow)
  113. else()
  114. find_package(Threads REQUIRED)
  115. find_package(MbedTLS REQUIRED)
  116. list(APPEND EXTERNAL_INCLUDES ${MBEDTLS_INCLUDE_DIRS})
  117. set(THREADS_PREFER_PTHREAD_FLAG ON)
  118. list(APPEND EXTRA_LIBS ${MBEDTLS_LIBRARIES} Threads::Threads)
  119. if(MSVC)
  120. add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS _USE_MATH_DEFINES)
  121. add_definitions(/wd4068 /wd4244 /wd4018 /wd4101 /wd4102 /wd4142)
  122. endif()
  123. endif()
  124. if (NOT BELL_DISABLE_MQTT)
  125. file(GLOB MQTT_SOURCES "external/mqtt/*.c")
  126. list(APPEND SOURCES ${MQTT_SOURCES})
  127. list(APPEND EXTRA_INCLUDES "external/mqtt/include")
  128. else()
  129. list(REMOVE_ITEM SOURCES "${IO_DIR}/BellMQTTClient.cpp")
  130. endif()
  131. if(NOT BELL_DISABLE_CODECS)
  132. file(GLOB EXTRA_SOURCES "main/audio-containers/*.cpp" "main/audio-codec/*.cpp" "main/audio-codec/*.c" "main/audio-dsp/*.cpp" "main/audio-dsp/*.c")
  133. list(APPEND SOURCES "${EXTRA_SOURCES}")
  134. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/DecoderGlobals.cpp")
  135. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/BaseCodec.cpp")
  136. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AudioCodecs.cpp")
  137. list(APPEND EXTRA_INCLUDES "main/audio-containers/include")
  138. # AAC-LC codec
  139. if(BELL_CODEC_AAC)
  140. file(GLOB LIBHELIX_AAC_SOURCES "external/libhelix-aac/*.c")
  141. list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES})
  142. list(APPEND EXTERNAL_INCLUDES "external/libhelix-aac")
  143. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AACDecoder.cpp")
  144. list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC")
  145. endif()
  146. # MP3 codec
  147. if(BELL_CODEC_MP3)
  148. file(GLOB LIBHELIX_MP3_SOURCES "external/libhelix-mp3/*.c")
  149. list(APPEND LIBHELIX_SOURCES ${LIBHELIX_MP3_SOURCES})
  150. list(APPEND EXTERNAL_INCLUDES "external/libhelix-mp3")
  151. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/MP3Decoder.cpp")
  152. list(APPEND CODEC_FLAGS "-DBELL_CODEC_MP3")
  153. endif()
  154. # MP3 codec
  155. # if(BELL_CODEC_ALAC)
  156. # file(GLOB ALAC_SOURCES "external/alac/*.c" "external/alac/*.cpp")
  157. # list(APPEND ALAC_SOURCES ${ALAC_SOURCES})
  158. # list(APPEND EXTRA_INCLUDES "external/alac")
  159. # # list(APPEND SOURCES "${AUDIO_DIR}/codec/ALACDecoder.cpp")
  160. # list(APPEND CODEC_FLAGS "-DBELL_CODEC_ALAC")
  161. # endif()
  162. # libhelix Cygwin workaround
  163. if(CYGWIN)
  164. # Both Cygwin and ESP are Unix-like so this seems to work (or, at least, compile)
  165. set_source_files_properties("${AUDIO_CODEC_DIR}/DecoderGlobals.cpp" ${LIBHELIX_SOURCES} PROPERTIES COMPILE_FLAGS "-DESP_PLATFORM")
  166. endif()
  167. list(APPEND SOURCES ${LIBHELIX_SOURCES})
  168. list(APPEND SOURCES ${ALAC_SOURCES})
  169. # Vorbis codec
  170. if(BELL_CODEC_VORBIS)
  171. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/VorbisDecoder.cpp")
  172. list(APPEND CODEC_FLAGS "-DBELL_CODEC_VORBIS")
  173. endif()
  174. # Opus codec
  175. if(BELL_CODEC_OPUS)
  176. set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF CACHE BOOL "")
  177. set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF)
  178. set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF CACHE BOOL "")
  179. set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
  180. set(MESSAGE_QUIET ON)
  181. add_subdirectory("external/opus")
  182. unset(MESSAGE_QUIET)
  183. target_compile_options(opus PRIVATE "-O3")
  184. list(APPEND EXTRA_LIBS Opus::opus)
  185. list(APPEND SOURCES "${AUDIO_CODEC_DIR}/OPUSDecoder.cpp")
  186. list(APPEND CODEC_FLAGS -DBELL_CODEC_OPUS)
  187. endif()
  188. # Enable global codecs
  189. string(REPLACE ";" " " CODEC_FLAGS "${CODEC_FLAGS}")
  190. set_source_files_properties("${AUDIO_CODEC_DIR}/AudioCodecs.cpp" PROPERTIES COMPILE_FLAGS "${CODEC_FLAGS}")
  191. else()
  192. list(REMOVE_ITEM SOURCES "${IO_DIR}/EncodedAudioStream.cpp")
  193. endif()
  194. if(NOT BELL_EXTERNAL_VORBIS STREQUAL "")
  195. message(STATUS "Using external Vorbis codec ${BELL_EXTERNAL_VORBIS}")
  196. list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_VORBIS})
  197. else()
  198. file(GLOB TREMOR_SOURCES "external/tremor/*.c")
  199. list(REMOVE_ITEM TREMOR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/tremor/ivorbisfile_example.c")
  200. list(APPEND SOURCES ${TREMOR_SOURCES})
  201. list(APPEND EXTERNAL_INCLUDES "external/tremor")
  202. endif()
  203. if(NOT BELL_DISABLE_SINKS)
  204. set(PLATFORM "unix")
  205. if(ESP_PLATFORM)
  206. set(PLATFORM "esp")
  207. endif()
  208. # Add all built-in audio sinks
  209. file(GLOB SINK_SOURCES "${AUDIO_SINKS_DIR}/${PLATFORM}/*.cpp" "${AUDIO_SINKS_DIR}/${PLATFORM}/*.c")
  210. list(APPEND EXTRA_INCLUDES "main/audio-sinks/include/${PLATFORM}")
  211. # Find ALSA if required, else remove the sink
  212. if(BELL_SINK_ALSA)
  213. find_package(ALSA REQUIRED)
  214. list(APPEND EXTERNAL_INCLUDES ${ALSA_INCLUDE_DIRS})
  215. list(APPEND EXTRA_LIBS ${ALSA_LIBRARIES})
  216. else()
  217. list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/ALSAAudioSink.cpp")
  218. endif()
  219. # Find PortAudio if required, else remove the sink
  220. if(BELL_SINK_PORTAUDIO)
  221. find_package(Portaudio REQUIRED)
  222. list(APPEND EXTERNAL_INCLUDES ${PORTAUDIO_INCLUDE_DIRS})
  223. list(APPEND EXTRA_LIBS ${PORTAUDIO_LIBRARIES})
  224. else()
  225. list(REMOVE_ITEM SINK_SOURCES "${AUDIO_SINKS_DIR}/unix/PortAudioSink.cpp")
  226. endif()
  227. list(APPEND SOURCES ${SINK_SOURCES})
  228. endif()
  229. if(NOT BELL_ONLY_CJSON)
  230. add_subdirectory(external/nlohmann_json)
  231. list(APPEND EXTRA_LIBS nlohmann_json::nlohmann_json)
  232. endif()
  233. if(BELL_EXTERNAL_CJSON)
  234. list(APPEND EXTRA_LIBS ${BELL_EXTERNAL_CJSON})
  235. else()
  236. list(APPEND SOURCES "external/cJSON/cJSON.c")
  237. list(APPEND EXTERNAL_INCLUDES "external/cJSON")
  238. endif()
  239. if (NOT BELL_DISABLE_FMT)
  240. list(APPEND EXTERNAL_INCLUDES "external/fmt/include")
  241. endif()
  242. if(WIN32 OR UNIX)
  243. list(APPEND SOURCES "external/mdnssvc/mdns.c" "external/mdnssvc/mdnsd.c")
  244. list(APPEND EXTERNAL_INCLUDES "external/mdnssvc")
  245. endif()
  246. # file(GLOB CIVET_SRC "external/civetweb/*.c" "external/civetweb/*.inl" "external/civetweb/*.cpp")
  247. # list(APPEND SOURCES ${CIVET_SRC})
  248. # list(APPEND EXTRA_INCLUDES "external/civetweb/include")
  249. add_library(bell STATIC ${SOURCES})
  250. # Add Apple Bonjour compatibility library for Linux
  251. if(UNIX AND NOT APPLE)
  252. if (BELL_DISABLE_AVAHI)
  253. add_compile_definitions(BELL_DISABLE_AVAHI)
  254. else()
  255. list(APPEND EXTRA_LIBS avahi-client avahi-common)
  256. endif()
  257. endif()
  258. # PUBLIC to propagate esp-idf includes to bell dependents
  259. target_link_libraries(bell PUBLIC ${EXTRA_LIBS})
  260. target_include_directories(bell PUBLIC ${EXTRA_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
  261. target_include_directories(bell SYSTEM PUBLIC ${EXTERNAL_INCLUDES})
  262. target_compile_definitions(bell PUBLIC PB_ENABLE_MALLOC FMT_HEADER_ONLY)
  263. if(BELL_DISABLE_CODECS)
  264. target_compile_definitions(bell PUBLIC BELL_DISABLE_CODECS)
  265. endif()
  266. if(BELL_VORBIS_FLOAT)
  267. target_compile_definitions(bell PUBLIC BELL_VORBIS_FLOAT)
  268. endif()
  269. if(BELL_DISABLE_FMT)
  270. target_compile_definitions(bell PUBLIC BELL_DISABLE_FMT)
  271. endif()
  272. if(BELL_DISABLE_REGEX)
  273. target_compile_definitions(bell PUBLIC BELL_DISABLE_REGEX)
  274. endif()
  275. if(BELL_ONLY_CJSON)
  276. target_compile_definitions(bell PUBLIC BELL_ONLY_CJSON)
  277. endif()
  278. if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "SunOS")
  279. target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
  280. endif()