1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindSDL_sound
6-------------
7
8Locates the SDL_sound library
9
10
11
12This module depends on SDL being found and must be called AFTER
13FindSDL.cmake is called.
14
15This module defines
16
17::
18
19  SDL_SOUND_INCLUDE_DIR, where to find SDL_sound.h
20  SDL_SOUND_FOUND, if false, do not try to link to SDL_sound
21  SDL_SOUND_LIBRARIES, this contains the list of libraries that you need
22    to link against.
23  SDL_SOUND_EXTRAS, this is an optional variable for you to add your own
24    flags to SDL_SOUND_LIBRARIES. This is prepended to SDL_SOUND_LIBRARIES.
25    This is available mostly for cases this module failed to anticipate for
26    and you must add additional flags. This is marked as ADVANCED.
27  SDL_SOUND_VERSION_STRING, human-readable string containing the
28    version of SDL_sound
29
30
31
32This module also defines (but you shouldn't need to use directly)
33
34::
35
36   SDL_SOUND_LIBRARY, the name of just the SDL_sound library you would link
37   against. Use SDL_SOUND_LIBRARIES for you link instructions and not this one.
38
39And might define the following as needed
40
41::
42
43   MIKMOD_LIBRARY
44   MODPLUG_LIBRARY
45   OGG_LIBRARY
46   VORBIS_LIBRARY
47   SMPEG_LIBRARY
48   FLAC_LIBRARY
49   SPEEX_LIBRARY
50
51
52
53Typically, you should not use these variables directly, and you should
54use SDL_SOUND_LIBRARIES which contains SDL_SOUND_LIBRARY and the other
55audio libraries (if needed) to successfully compile on your system.
56
57Created by Eric Wing.  This module is a bit more complicated than the
58other FindSDL* family modules.  The reason is that SDL_sound can be
59compiled in a large variety of different ways which are independent of
60platform.  SDL_sound may dynamically link against other 3rd party
61libraries to get additional codec support, such as Ogg Vorbis, SMPEG,
62ModPlug, MikMod, FLAC, Speex, and potentially others.  Under some
63circumstances which I don't fully understand, there seems to be a
64requirement that dependent libraries of libraries you use must also be
65explicitly linked against in order to successfully compile.  SDL_sound
66does not currently have any system in place to know how it was
67compiled.  So this CMake module does the hard work in trying to
68discover which 3rd party libraries are required for building (if any).
69This module uses a brute force approach to create a test program that
70uses SDL_sound, and then tries to build it.  If the build fails, it
71parses the error output for known symbol names to figure out which
72libraries are needed.
73
74Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that
75would correspond to the ./configure --prefix=$SDLDIR used in building
76SDL.
77
78On OSX, this will prefer the Framework version (if found) over others.
79People will have to manually change the cache values of SDL_LIBRARY to
80override this selectionor set the CMake environment CMAKE_INCLUDE_PATH
81to modify the search paths.
82#]=======================================================================]
83
84set(SDL_SOUND_EXTRAS "" CACHE STRING "SDL_sound extra flags")
85mark_as_advanced(SDL_SOUND_EXTRAS)
86
87# Find SDL_sound.h
88find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h
89  HINTS
90    ENV SDLSOUNDDIR
91    ENV SDLDIR
92  PATH_SUFFIXES SDL
93                # path suffixes to search inside ENV{SDLDIR}
94                include/SDL include/SDL12 include/SDL11 include
95  )
96
97find_library(SDL_SOUND_LIBRARY
98  NAMES SDL_sound
99  HINTS
100    ENV SDLSOUNDDIR
101    ENV SDLDIR
102  PATH_SUFFIXES lib VisualC/win32lib
103  )
104
105if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY)
106
107  # CMake is giving me problems using TRY_COMPILE with the CMAKE_FLAGS
108  # for the :STRING syntax if I have multiple values contained in a
109  # single variable. This is a problem for the SDL_LIBRARY variable
110  # because it does just that. When I feed this variable to the command,
111  # only the first value gets the appropriate modifier (e.g. -I) and
112  # the rest get dropped.
113  # To get multiple single variables to work, I must separate them with a "\;"
114  # I could go back and modify the FindSDL.cmake module, but that's kind of painful.
115  # The solution would be to try something like:
116  # string(APPEND SDL_TRY_COMPILE_LIBRARY_LIST "\;${CMAKE_THREAD_LIBS_INIT}")
117  # Instead, it was suggested on the mailing list to write a temporary CMakeLists.txt
118  # with a temporary test project and invoke that with TRY_COMPILE.
119  # See message thread "Figuring out dependencies for a library in order to build"
120  # 2005-07-16
121  #     try_compile(
122  #             MY_RESULT
123  #             ${CMAKE_BINARY_DIR}
124  #             ${PROJECT_SOURCE_DIR}/DetermineSoundLibs.c
125  #             CMAKE_FLAGS
126  #                     -DINCLUDE_DIRECTORIES:STRING=${SDL_INCLUDE_DIR}\;${SDL_SOUND_INCLUDE_DIR}
127  #                     -DLINK_LIBRARIES:STRING=${SDL_SOUND_LIBRARY}\;${SDL_LIBRARY}
128  #             OUTPUT_VARIABLE MY_OUTPUT
129  #     )
130
131  # To minimize external dependencies, create a sdlsound test program
132  # which will be used to figure out if additional link dependencies are
133  # required for the link phase.
134  file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/DetermineSoundLibs.c
135    "#include \"SDL_sound.h\"
136    #include \"SDL.h\"
137    int main(int argc, char* argv[])
138    {
139        Sound_AudioInfo desired;
140        Sound_Sample* sample;
141
142        SDL_Init(0);
143        Sound_Init();
144
145        /* This doesn't actually have to work, but Init() is a no-op
146         * for some of the decoders, so this should force more symbols
147         * to be pulled in.
148         */
149        sample = Sound_NewSampleFromFile(argv[1], &desired, 4096);
150
151        Sound_Quit();
152        SDL_Quit();
153        return 0;
154     }"
155  )
156
157  # Calling
158  # target_link_libraries(DetermineSoundLibs "${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
159  # causes problems when SDL_LIBRARY looks like
160  # /Library/Frameworks/SDL.framework;-framework Cocoa
161  # The ;-framework Cocoa seems to be confusing CMake once the OS X
162  # framework support was added. I was told that breaking up the list
163  # would fix the problem.
164  set(TMP_TRY_LIBS)
165  foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
166    string(APPEND TMP_TRY_LIBS " \"${lib}\"")
167  endforeach()
168
169
170  # Write the CMakeLists.txt and test project
171  # Weird, this is still sketchy. If I don't quote the variables
172  # in the TARGET_LINK_LIBRARIES, I seem to loose everything
173  # in the SDL_LIBRARY string after the "-framework".
174  # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work.
175  file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt
176    "cmake_minimum_required(VERSION ${CMAKE_VERSION})
177     project(DetermineSoundLibs)
178     include_directories(${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
179     add_executable(DetermineSoundLibs DetermineSoundLibs.c)
180     target_link_libraries(DetermineSoundLibs ${TMP_TRY_LIBS})"
181    )
182
183  try_compile(
184    MY_RESULT
185    ${PROJECT_BINARY_DIR}/CMakeTmp
186    ${PROJECT_BINARY_DIR}/CMakeTmp
187    DetermineSoundLibs
188    OUTPUT_VARIABLE MY_OUTPUT
189    )
190
191
192  if(NOT MY_RESULT)
193
194    # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically.
195    # I think Timidity is also compiled in statically.
196    # I've never had to explcitly link against Quicktime, so I'll skip that for now.
197
198    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY})
199
200    # Find MikMod
201    if("${MY_OUTPUT}" MATCHES "MikMod_")
202      find_library(MIKMOD_LIBRARY
203        NAMES libmikmod-coreaudio mikmod
204        PATHS
205          ENV MIKMODDIR
206          ENV SDLSOUNDDIR
207          ENV SDLDIR
208          /opt
209        PATH_SUFFIXES
210          lib
211      )
212      if(MIKMOD_LIBRARY)
213        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY})
214      endif(MIKMOD_LIBRARY)
215    endif("${MY_OUTPUT}" MATCHES "MikMod_")
216
217    # Find ModPlug
218    if("${MY_OUTPUT}" MATCHES "MODPLUG_")
219      find_library(MODPLUG_LIBRARY
220        NAMES modplug
221        PATHS
222          ENV MODPLUGDIR
223          ENV SDLSOUNDDIR
224          ENV SDLDIR
225          /opt
226        PATH_SUFFIXES
227          lib
228      )
229      if(MODPLUG_LIBRARY)
230        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY})
231      endif()
232    endif()
233
234
235    # Find Ogg and Vorbis
236    if("${MY_OUTPUT}" MATCHES "ov_")
237      find_library(VORBIS_LIBRARY
238        NAMES vorbis Vorbis VORBIS
239        PATHS
240          ENV VORBISDIR
241          ENV OGGDIR
242          ENV SDLSOUNDDIR
243          ENV SDLDIR
244          /opt
245        PATH_SUFFIXES
246          lib
247        )
248      if(VORBIS_LIBRARY)
249        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY})
250      endif()
251
252      find_library(OGG_LIBRARY
253        NAMES ogg Ogg OGG
254        PATHS
255          ENV OGGDIR
256          ENV VORBISDIR
257          ENV SDLSOUNDDIR
258          ENV SDLDIR
259          /opt
260        PATH_SUFFIXES
261          lib
262         )
263      if(OGG_LIBRARY)
264        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
265      endif()
266    endif()
267
268
269    # Find SMPEG
270    if("${MY_OUTPUT}" MATCHES "SMPEG_")
271      find_library(SMPEG_LIBRARY
272        NAMES smpeg SMPEG Smpeg SMpeg
273        PATHS
274          ENV SMPEGDIR
275          ENV SDLSOUNDDIR
276          ENV SDLDIR
277          /opt
278        PATH_SUFFIXES
279          lib
280        )
281      if(SMPEG_LIBRARY)
282        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY})
283      endif()
284    endif()
285
286
287    # Find FLAC
288    if("${MY_OUTPUT}" MATCHES "FLAC_")
289      find_library(FLAC_LIBRARY
290        NAMES flac FLAC
291        PATHS
292          ENV FLACDIR
293          ENV SDLSOUNDDIR
294          ENV SDLDIR
295          /opt
296        PATH_SUFFIXES
297          lib
298        )
299      if(FLAC_LIBRARY)
300        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY})
301      endif()
302    endif()
303
304
305    # Hmmm...Speex seems to depend on Ogg. This might be a problem if
306    # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull
307    # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff
308    # above for here or if two ogg entries will screw up things.
309    if("${MY_OUTPUT}" MATCHES "speex_")
310      find_library(SPEEX_LIBRARY
311        NAMES speex SPEEX
312        PATHS
313          ENV SPEEXDIR
314          ENV SDLSOUNDDIR
315          ENV SDLDIR
316          /opt
317        PATH_SUFFIXES
318          lib
319        )
320      if(SPEEX_LIBRARY)
321        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY})
322      endif()
323
324      # Find OGG (needed for Speex)
325      # We might have already found Ogg for Vorbis, so skip it if so.
326      if(NOT OGG_LIBRARY)
327        find_library(OGG_LIBRARY
328          NAMES ogg Ogg OGG
329          PATHS
330            ENV OGGDIR
331            ENV VORBISDIR
332            ENV SPEEXDIR
333            ENV SDLSOUNDDIR
334            ENV SDLDIR
335            /opt
336          PATH_SUFFIXES lib
337          )
338        if(OGG_LIBRARY)
339          set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
340        endif()
341      endif()
342    endif()
343
344    set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP})
345  else()
346    set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARY})
347  endif()
348 endif()
349
350if(SDL_SOUND_INCLUDE_DIR AND EXISTS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h")
351  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SOUND_VER_MAJOR[ \t]+[0-9]+$")
352  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MINOR_LINE REGEX "^#define[ \t]+SOUND_VER_MINOR[ \t]+[0-9]+$")
353  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_PATCH_LINE REGEX "^#define[ \t]+SOUND_VER_PATCH[ \t]+[0-9]+$")
354  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MAJOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MAJOR "${SDL_SOUND_VERSION_MAJOR_LINE}")
355  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MINOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MINOR "${SDL_SOUND_VERSION_MINOR_LINE}")
356  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_PATCH[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_PATCH "${SDL_SOUND_VERSION_PATCH_LINE}")
357  set(SDL_SOUND_VERSION_STRING ${SDL_SOUND_VERSION_MAJOR}.${SDL_SOUND_VERSION_MINOR}.${SDL_SOUND_VERSION_PATCH})
358  unset(SDL_SOUND_VERSION_MAJOR_LINE)
359  unset(SDL_SOUND_VERSION_MINOR_LINE)
360  unset(SDL_SOUND_VERSION_PATCH_LINE)
361  unset(SDL_SOUND_VERSION_MAJOR)
362  unset(SDL_SOUND_VERSION_MINOR)
363  unset(SDL_SOUND_VERSION_PATCH)
364endif()
365
366include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
367
368FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_sound
369                                  REQUIRED_VARS SDL_SOUND_LIBRARY SDL_SOUND_INCLUDE_DIR
370                                  VERSION_VAR SDL_SOUND_VERSION_STRING)
371