CMakeLists.txt 13 KB

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