CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. # TODO
  2. # - backend selection via command line, rather than simply detecting headers.
  3. cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
  4. project(cubeb
  5. VERSION 0.0.0)
  6. option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
  7. option(BUILD_RUST_LIBS "Build rust backends" OFF)
  8. option(BUNDLE_SPEEX "Bundle the speex library" OFF)
  9. option(LAZY_LOAD_LIBS "Lazily load shared libraries" ON)
  10. option(USE_SANITIZERS "Use sanitizers" ON)
  11. if(NOT CMAKE_BUILD_TYPE)
  12. set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
  13. "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
  14. endif()
  15. if (NOT MSVC)
  16. set(CMAKE_C_STANDARD 99)
  17. set(CMAKE_CXX_STANDARD 17)
  18. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  19. set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
  20. endif()
  21. if(USE_SANITIZERS)
  22. if(NOT COMMAND add_sanitizers)
  23. list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cubeb/cmake/sanitizers-cmake/cmake")
  24. find_package(Sanitizers)
  25. if(NOT COMMAND add_sanitizers)
  26. message(FATAL_ERROR "Could not find sanitizers-cmake: run\n\tgit submodule update --init --recursive\nin base git checkout")
  27. endif()
  28. endif()
  29. else()
  30. macro(add_sanitizers UNUSED)
  31. endmacro()
  32. endif()
  33. if (BUILD_RUST_LIBS)
  34. if(EXISTS "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-pulse-rs")
  35. set(USE_PULSE_RUST 1)
  36. endif()
  37. if(EXISTS "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-coreaudio-rs")
  38. set(USE_AUDIOUNIT_RUST 1)
  39. endif()
  40. endif()
  41. # On OS/2, visibility attribute is not supported.
  42. if(NOT OS2)
  43. set(CMAKE_C_VISIBILITY_PRESET hidden)
  44. set(CMAKE_CXX_VISIBILITY_PRESET hidden)
  45. set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
  46. endif()
  47. set(CMAKE_CXX_WARNING_LEVEL 4)
  48. if(NOT MSVC)
  49. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter")
  50. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -fno-exceptions -fno-rtti")
  51. else()
  52. #string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Disable RTTI
  53. #string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Disable Exceptions
  54. endif()
  55. add_library(cubeb
  56. cubeb/src/cubeb.c
  57. cubeb/src/cubeb_mixer.cpp
  58. cubeb/src/cubeb_resampler.cpp
  59. cubeb/src/cubeb_log.cpp
  60. cubeb/src/cubeb_strings.c
  61. cubeb/src/cubeb_utils.cpp
  62. )
  63. dolphin_disable_warnings(cubeb)
  64. target_include_directories(cubeb
  65. PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/cubeb/include> $<INSTALL_INTERFACE:include>
  66. )
  67. set_target_properties(cubeb PROPERTIES
  68. VERSION ${cubeb_VERSION}
  69. SOVERSION ${cubeb_VERSION_MAJOR}
  70. )
  71. add_sanitizers(cubeb)
  72. include(GenerateExportHeader)
  73. generate_export_header(cubeb EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/cubeb_export.h)
  74. target_include_directories(cubeb
  75. PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/exports>
  76. )
  77. include(GNUInstallDirs)
  78. install(DIRECTORY ${CMAKE_SOURCE_DIR}/cubeb/include/${PROJECT_NAME} TYPE INCLUDE)
  79. install(DIRECTORY ${CMAKE_BINARY_DIR}/exports/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
  80. include(CMakePackageConfigHelpers)
  81. write_basic_package_version_file(
  82. "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
  83. COMPATIBILITY SameMajorVersion
  84. )
  85. configure_package_config_file(
  86. "cubeb/Config.cmake.in"
  87. "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
  88. INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
  89. )
  90. install(
  91. FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
  92. DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
  93. )
  94. install(TARGETS cubeb EXPORT "${PROJECT_NAME}Targets")
  95. install(
  96. EXPORT "${PROJECT_NAME}Targets"
  97. NAMESPACE "${PROJECT_NAME}::"
  98. DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
  99. )
  100. if(NOT BUNDLE_SPEEX)
  101. find_package(PkgConfig)
  102. if(PKG_CONFIG_FOUND)
  103. pkg_check_modules(speexdsp IMPORTED_TARGET speexdsp)
  104. if(speexdsp_FOUND)
  105. add_library(speex ALIAS PkgConfig::speexdsp)
  106. endif()
  107. endif()
  108. endif()
  109. if(NOT TARGET speex)
  110. add_library(speex OBJECT cubeb/subprojects/speex/resample.c)
  111. dolphin_disable_warnings(speex)
  112. set_target_properties(speex PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
  113. target_include_directories(speex INTERFACE cubeb/subprojects)
  114. target_compile_definitions(speex PUBLIC
  115. OUTSIDE_SPEEX
  116. FLOATING_POINT
  117. EXPORT=
  118. RANDOM_PREFIX=speex
  119. )
  120. endif()
  121. # $<BUILD_INTERFACE:> required because of https://gitlab.kitware.com/cmake/cmake/-/issues/15415
  122. target_link_libraries(cubeb PRIVATE $<BUILD_INTERFACE:speex>)
  123. include(CheckIncludeFiles)
  124. # Threads needed by cubeb_log, _pulse, _alsa, _jack, _sndio, _oss and _sun
  125. set(THREADS_PREFER_PTHREAD_FLAG ON)
  126. find_package(Threads)
  127. target_link_libraries(cubeb PRIVATE Threads::Threads)
  128. if(LAZY_LOAD_LIBS)
  129. check_include_files(pulse/pulseaudio.h USE_PULSE)
  130. check_include_files(alsa/asoundlib.h USE_ALSA)
  131. check_include_files(jack/jack.h USE_JACK)
  132. check_include_files(sndio.h USE_SNDIO)
  133. #check_include_files(aaudio/AAudio.h USE_AAUDIO)
  134. set(USE_AAUDIO OFF) # too new for the Android versions we're targetting
  135. if(USE_PULSE OR USE_ALSA OR USE_JACK OR USE_SNDIO OR USE_AAUDIO)
  136. target_link_libraries(cubeb PRIVATE ${CMAKE_DL_LIBS})
  137. if(ANDROID)
  138. target_compile_definitions(cubeb PRIVATE __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
  139. endif()
  140. endif()
  141. else()
  142. find_package(PkgConfig REQUIRED)
  143. pkg_check_modules(libpulse IMPORTED_TARGET libpulse)
  144. if(libpulse_FOUND)
  145. set(USE_PULSE ON)
  146. target_compile_definitions(cubeb PRIVATE DISABLE_LIBPULSE_DLOPEN)
  147. target_link_libraries(cubeb PRIVATE PkgConfig::libpulse)
  148. endif()
  149. pkg_check_modules(alsa IMPORTED_TARGET alsa)
  150. if(alsa_FOUND)
  151. set(USE_ALSA ON)
  152. target_compile_definitions(cubeb PRIVATE DISABLE_LIBASOUND_DLOPEN)
  153. target_link_libraries(cubeb PRIVATE PkgConfig::alsa)
  154. endif()
  155. pkg_check_modules(jack IMPORTED_TARGET jack)
  156. if(jack_FOUND)
  157. set(USE_JACK ON)
  158. target_compile_definitions(cubeb PRIVATE DISABLE_LIBJACK_DLOPEN)
  159. target_link_libraries(cubeb PRIVATE PkgConfig::jack)
  160. endif()
  161. check_include_files(sndio.h USE_SNDIO)
  162. if(USE_SNDIO)
  163. target_compile_definitions(cubeb PRIVATE DISABLE_LIBSNDIO_DLOPEN)
  164. target_link_libraries(cubeb PRIVATE sndio)
  165. endif()
  166. #check_include_files(aaudio/AAudio.h USE_AAUDIO)
  167. set(USE_AAUDIO OFF) # too new for the Android versions we're targetting
  168. if(USE_AAUDIO)
  169. target_compile_definitions(cubeb PRIVATE DISABLE_LIBAAUDIO_DLOPEN)
  170. target_link_libraries(cubeb PRIVATE aaudio)
  171. endif()
  172. endif()
  173. if(USE_PULSE)
  174. target_sources(cubeb PRIVATE cubeb/src/cubeb_pulse.c)
  175. target_compile_definitions(cubeb PRIVATE USE_PULSE)
  176. endif()
  177. if(USE_ALSA)
  178. target_sources(cubeb PRIVATE cubeb/src/cubeb_alsa.c)
  179. target_compile_definitions(cubeb PRIVATE USE_ALSA)
  180. endif()
  181. if(USE_JACK)
  182. target_sources(cubeb PRIVATE cubeb/src/cubeb_jack.cpp)
  183. target_compile_definitions(cubeb PRIVATE USE_JACK)
  184. endif()
  185. if(USE_SNDIO)
  186. target_sources(cubeb PRIVATE cubeb/src/cubeb_sndio.c)
  187. target_compile_definitions(cubeb PRIVATE USE_SNDIO)
  188. endif()
  189. if(USE_AAUDIO)
  190. target_sources(cubeb PRIVATE cubeb/src/cubeb_aaudio.cpp)
  191. target_compile_definitions(cubeb PRIVATE USE_AAUDIO)
  192. # set this definition to enable low latency mode. Possibly bad for battery
  193. target_compile_definitions(cubeb PRIVATE CUBEB_AAUDIO_LOW_LATENCY)
  194. # set this definition to enable power saving mode. Possibly resulting
  195. # in high latency
  196. # target_compile_definitions(cubeb PRIVATE CUBEB_AAUDIO_LOW_POWER_SAVING)
  197. # set this mode to make the backend use an exclusive stream.
  198. # will decrease latency.
  199. # target_compile_definitions(cubeb PRIVATE CUBEB_AAUDIO_EXCLUSIVE_STREAM)
  200. endif()
  201. check_include_files(AudioUnit/AudioUnit.h USE_AUDIOUNIT)
  202. if(USE_AUDIOUNIT)
  203. target_sources(cubeb PRIVATE
  204. cubeb/src/cubeb_audiounit.cpp
  205. cubeb/src/cubeb_osx_run_loop.cpp)
  206. target_compile_definitions(cubeb PRIVATE USE_AUDIOUNIT)
  207. target_link_libraries(cubeb PRIVATE "-framework AudioUnit" "-framework CoreAudio" "-framework CoreServices")
  208. endif()
  209. check_include_files(audioclient.h USE_WASAPI)
  210. if(USE_WASAPI)
  211. target_sources(cubeb PRIVATE
  212. cubeb/src/cubeb_wasapi.cpp)
  213. target_compile_definitions(cubeb PRIVATE USE_WASAPI)
  214. target_link_libraries(cubeb PRIVATE avrt ole32 ksuser)
  215. endif()
  216. check_include_files("windows.h;mmsystem.h" USE_WINMM)
  217. if(USE_WINMM)
  218. target_sources(cubeb PRIVATE
  219. cubeb/src/cubeb_winmm.c)
  220. target_compile_definitions(cubeb PRIVATE USE_WINMM)
  221. target_link_libraries(cubeb PRIVATE winmm)
  222. endif()
  223. check_include_files(SLES/OpenSLES.h USE_OPENSL)
  224. if(USE_OPENSL)
  225. target_sources(cubeb PRIVATE
  226. cubeb/src/cubeb_opensl.cpp
  227. cubeb/src/cubeb-jni.cpp)
  228. target_compile_definitions(cubeb PRIVATE USE_OPENSL)
  229. target_link_libraries(cubeb PRIVATE OpenSLES)
  230. endif()
  231. check_include_files(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
  232. if(HAVE_SYS_SOUNDCARD_H)
  233. try_compile(USE_OSS "${PROJECT_BINARY_DIR}/compile_tests"
  234. ${PROJECT_SOURCE_DIR}/cubeb/cmake/compile_tests/oss_is_v4.c)
  235. if(USE_OSS)
  236. # strlcpy is not available on BSD systems that use glibc,
  237. # like Debian kfreebsd, so try using libbsd if available
  238. include(CheckSymbolExists)
  239. check_symbol_exists(strlcpy string.h HAVE_STRLCPY)
  240. if(NOT HAVE_STRLCPY)
  241. pkg_check_modules(libbsd-overlay IMPORTED_TARGET libbsd-overlay)
  242. if(libbsd-overlay_FOUND)
  243. target_link_libraries(cubeb PRIVATE PkgConfig::libbsd-overlay)
  244. set(HAVE_STRLCPY true)
  245. endif()
  246. endif()
  247. if (HAVE_STRLCPY)
  248. target_sources(cubeb PRIVATE
  249. cubeb/src/cubeb_oss.c)
  250. target_compile_definitions(cubeb PRIVATE USE_OSS)
  251. endif()
  252. endif()
  253. endif()
  254. check_include_files(android/log.h USE_AUDIOTRACK)
  255. if(USE_AUDIOTRACK)
  256. target_sources(cubeb PRIVATE
  257. cubeb/src/cubeb_audiotrack.c)
  258. target_compile_definitions(cubeb PRIVATE USE_AUDIOTRACK)
  259. target_link_libraries(cubeb PRIVATE log)
  260. endif()
  261. check_include_files(sys/audioio.h USE_SUN)
  262. if(USE_SUN)
  263. target_sources(cubeb PRIVATE
  264. cubeb/src/cubeb_sun.c)
  265. target_compile_definitions(cubeb PRIVATE USE_SUN)
  266. endif()
  267. check_include_files(kai.h USE_KAI)
  268. if(USE_KAI)
  269. target_sources(cubeb PRIVATE
  270. cubeb/src/cubeb_kai.c)
  271. target_compile_definitions(cubeb PRIVATE USE_KAI)
  272. target_link_libraries(cubeb PRIVATE kai)
  273. endif()
  274. if(USE_PULSE AND USE_PULSE_RUST)
  275. include(ExternalProject)
  276. set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust)
  277. ExternalProject_Add(
  278. cubeb_pulse_rs
  279. DOWNLOAD_COMMAND ""
  280. CONFIGURE_COMMAND ""
  281. BUILD_COMMAND cargo build COMMAND cargo build --release
  282. BUILD_ALWAYS ON
  283. BINARY_DIR "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-pulse-rs"
  284. INSTALL_COMMAND ""
  285. LOG_BUILD ON)
  286. add_dependencies(cubeb cubeb_pulse_rs)
  287. target_compile_definitions(cubeb PRIVATE USE_PULSE_RUST)
  288. target_link_libraries(cubeb PRIVATE
  289. debug "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-pulse-rs/target/debug/libcubeb_pulse.a"
  290. optimized "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-pulse-rs/target/release/libcubeb_pulse.a" pulse)
  291. endif()
  292. if(USE_AUDIOUNIT AND USE_AUDIOUNIT_RUST)
  293. include(ExternalProject)
  294. set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust)
  295. ExternalProject_Add(
  296. cubeb_coreaudio_rs
  297. DOWNLOAD_COMMAND ""
  298. CONFIGURE_COMMAND ""
  299. BUILD_COMMAND cargo build COMMAND cargo build --release
  300. BUILD_ALWAYS ON
  301. BINARY_DIR "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-coreaudio-rs"
  302. INSTALL_COMMAND ""
  303. LOG_BUILD ON)
  304. add_dependencies(cubeb cubeb_coreaudio_rs)
  305. target_compile_definitions(cubeb PRIVATE USE_AUDIOUNIT_RUST)
  306. target_link_libraries(cubeb PRIVATE
  307. debug "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-coreaudio-rs/target/debug/libcubeb_coreaudio.a"
  308. optimized "${PROJECT_SOURCE_DIR}/cubeb/src/cubeb-coreaudio-rs/target/release/libcubeb_coreaudio.a")
  309. endif()
  310. add_library(cubeb::cubeb ALIAS cubeb)