1# - Find SDL2
2# Find the SDL2 headers and libraries
3#
4#  SDL2::SDL2 - Imported target to use for building a library
5#  SDL2::SDL2main - Imported interface target to use if you want SDL and SDLmain.
6#  SDL2_FOUND - True if SDL2 was found.
7#  SDL2_DYNAMIC - If we found a DLL version of SDL (meaning you might want to copy a DLL from SDL2::SDL2)
8#
9# Original Author:
10# 2015 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
11#
12# Copyright Sensics, Inc. 2015.
13# Distributed under the Boost Software License, Version 1.0.
14# (See accompanying file LICENSE_1_0.txt or copy at
15# http://www.boost.org/LICENSE_1_0.txt)
16
17# Set up architectures (for windows) and prefixes (for mingw builds)
18if(WIN32)
19	if(MINGW)
20		include(MinGWSearchPathExtras OPTIONAL)
21		if(MINGWSEARCH_TARGET_TRIPLE)
22			set(SDL2_PREFIX ${MINGWSEARCH_TARGET_TRIPLE})
23		endif()
24	endif()
25	if(CMAKE_SIZEOF_VOID_P EQUAL 8)
26		set(SDL2_LIB_PATH_SUFFIX lib/x64)
27		if(NOT MSVC AND NOT SDL2_PREFIX)
28			set(SDL2_PREFIX x86_64-w64-mingw32)
29		endif()
30	else()
31		set(SDL2_LIB_PATH_SUFFIX lib/x86)
32		if(NOT MSVC AND NOT SDL2_PREFIX)
33			set(SDL2_PREFIX i686-w64-mingw32)
34		endif()
35	endif()
36endif()
37
38if(SDL2_PREFIX)
39	set(SDL2_ORIGPREFIXPATH ${CMAKE_PREFIX_PATH})
40	if(SDL2_ROOT_DIR)
41		list(APPEND CMAKE_PREFIX_PATH "${SDL2_ROOT_DIR}")
42	endif()
43	if(CMAKE_PREFIX_PATH)
44		foreach(_prefix ${CMAKE_PREFIX_PATH})
45			list(APPEND CMAKE_PREFIX_PATH "${_prefix}/${SDL2_PREFIX}")
46		endforeach()
47	endif()
48	if(MINGWSEARCH_PREFIXES)
49		list(APPEND CMAKE_PREFIX_PATH ${MINGWSEARCH_PREFIXES})
50	endif()
51endif()
52
53# Invoke pkgconfig for hints
54find_package(PkgConfig QUIET)
55set(SDL2_INCLUDE_HINTS)
56set(SDL2_LIB_HINTS)
57if(PKG_CONFIG_FOUND)
58	pkg_search_module(SDL2PC QUIET sdl2)
59	if(SDL2PC_INCLUDE_DIRS)
60		set(SDL2_INCLUDE_HINTS ${SDL2PC_INCLUDE_DIRS})
61	endif()
62	if(SDL2PC_LIBRARY_DIRS)
63		set(SDL2_LIB_HINTS ${SDL2PC_LIBRARY_DIRS})
64	endif()
65endif()
66
67include(FindPackageHandleStandardArgs)
68
69find_library(SDL2_LIBRARY
70	NAMES
71	SDL2
72	HINTS
73	${SDL2_LIB_HINTS}
74	PATHS
75	${SDL2_ROOT_DIR}
76	ENV SDL2DIR
77	PATH_SUFFIXES lib SDL2 ${SDL2_LIB_PATH_SUFFIX})
78
79set(_sdl2_framework FALSE)
80# Some special-casing if we've found/been given a framework.
81# Handles whether we're given the library inside the framework or the framework itself.
82if(APPLE AND "${SDL2_LIBRARY}" MATCHES "(/[^/]+)*.framework(/.*)?$")
83	set(_sdl2_framework TRUE)
84	set(SDL2_FRAMEWORK "${SDL2_LIBRARY}")
85	# Move up in the directory tree as required to get the framework directory.
86	while("${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework(/.*)$" AND NOT "${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework$")
87		get_filename_component(SDL2_FRAMEWORK "${SDL2_FRAMEWORK}" DIRECTORY)
88	endwhile()
89	if("${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework$")
90		set(SDL2_FRAMEWORK_NAME ${CMAKE_MATCH_1})
91		# If we found a framework, do a search for the header ahead of time that will be more likely to get the framework header.
92		find_path(SDL2_INCLUDE_DIR
93			NAMES
94			SDL_haptic.h # this file was introduced with SDL2
95			HINTS
96			"${SDL2_FRAMEWORK}/Headers/")
97	else()
98		# For some reason we couldn't get the framework directory itself.
99		# Shouldn't happen, but might if something is weird.
100		unset(SDL2_FRAMEWORK)
101	endif()
102endif()
103
104find_path(SDL2_INCLUDE_DIR
105	NAMES
106	SDL_haptic.h # this file was introduced with SDL2
107	HINTS
108	${SDL2_INCLUDE_HINTS}
109	PATHS
110	${SDL2_ROOT_DIR}
111	ENV SDL2DIR
112	PATH_SUFFIXES include include/sdl2 include/SDL2 SDL2)
113
114if(WIN32 AND SDL2_LIBRARY)
115	find_file(SDL2_RUNTIME_LIBRARY
116		NAMES
117		SDL2.dll
118		libSDL2.dll
119		HINTS
120		${SDL2_LIB_HINTS}
121		PATHS
122		${SDL2_ROOT_DIR}
123		ENV SDL2DIR
124		PATH_SUFFIXES bin lib ${SDL2_LIB_PATH_SUFFIX})
125endif()
126
127
128if(WIN32 OR ANDROID OR IOS OR (APPLE AND NOT _sdl2_framework))
129	set(SDL2_EXTRA_REQUIRED SDL2_SDLMAIN_LIBRARY)
130	find_library(SDL2_SDLMAIN_LIBRARY
131		NAMES
132		SDL2main
133		PATHS
134		${SDL2_ROOT_DIR}
135		ENV SDL2DIR
136		PATH_SUFFIXES lib ${SDL2_LIB_PATH_SUFFIX})
137endif()
138
139if(MINGW AND NOT SDL2PC_FOUND)
140	find_library(SDL2_MINGW_LIBRARY mingw32)
141	find_library(SDL2_MWINDOWS_LIBRARY mwindows)
142endif()
143
144if(SDL2_PREFIX)
145	# Restore things the way they used to be.
146	set(CMAKE_PREFIX_PATH ${SDL2_ORIGPREFIXPATH})
147endif()
148
149# handle the QUIETLY and REQUIRED arguments and set QUATLIB_FOUND to TRUE if
150# all listed variables are TRUE
151include(FindPackageHandleStandardArgs)
152find_package_handle_standard_args(SDL2
153	DEFAULT_MSG
154	SDL2_LIBRARY
155	SDL2_INCLUDE_DIR
156	${SDL2_EXTRA_REQUIRED})
157
158if(SDL2_FOUND)
159	if(NOT TARGET SDL2::SDL2)
160		# Create SDL2::SDL2
161		if(WIN32 AND SDL2_RUNTIME_LIBRARY)
162			set(SDL2_DYNAMIC TRUE)
163			add_library(SDL2::SDL2 SHARED IMPORTED)
164			set_target_properties(SDL2::SDL2
165				PROPERTIES
166				IMPORTED_IMPLIB "${SDL2_LIBRARY}"
167				IMPORTED_LOCATION "${SDL2_RUNTIME_LIBRARY}"
168				INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}"
169			)
170		else()
171			add_library(SDL2::SDL2 UNKNOWN IMPORTED)
172			if(SDL2_FRAMEWORK AND SDL2_FRAMEWORK_NAME)
173				# Handle the case that SDL2 is a framework and we were able to decompose it above.
174				set_target_properties(SDL2::SDL2 PROPERTIES
175					IMPORTED_LOCATION "${SDL2_FRAMEWORK}/${SDL2_FRAMEWORK_NAME}")
176			elseif(_sdl2_framework AND SDL2_LIBRARY MATCHES "(/[^/]+)*.framework$")
177				# Handle the case that SDL2 is a framework and SDL_LIBRARY is just the framework itself.
178
179				# This takes the basename of the framework, without the extension,
180				# and sets it (as a child of the framework) as the imported location for the target.
181				# This is the library symlink inside of the framework.
182				set_target_properties(SDL2::SDL2 PROPERTIES
183					IMPORTED_LOCATION "${SDL2_LIBRARY}/${CMAKE_MATCH_1}")
184			else()
185				# Handle non-frameworks (including non-Mac), as well as the case that we're given the library inside of the framework
186				set_target_properties(SDL2::SDL2 PROPERTIES
187					IMPORTED_LOCATION "${SDL2_LIBRARY}")
188			endif()
189			set_target_properties(SDL2::SDL2
190				PROPERTIES
191				INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}"
192			)
193		endif()
194
195		if(APPLE)
196			# Need Cocoa here, is always a framework
197			find_library(SDL2_COCOA_LIBRARY Cocoa)
198			list(APPEND SDL2_EXTRA_REQUIRED SDL2_COCOA_LIBRARY)
199			if(SDL2_COCOA_LIBRARY)
200				set_target_properties(SDL2::SDL2 PROPERTIES
201						IMPORTED_LINK_INTERFACE_LIBRARIES ${SDL2_COCOA_LIBRARY})
202			endif()
203		endif()
204
205
206		# Compute what to do with SDL2main
207		set(SDL2MAIN_LIBRARIES SDL2::SDL2)
208		add_library(SDL2::SDL2main INTERFACE IMPORTED)
209		if(SDL2_SDLMAIN_LIBRARY)
210			add_library(SDL2::SDL2main_real STATIC IMPORTED)
211			set_target_properties(SDL2::SDL2main_real
212				PROPERTIES
213				IMPORTED_LOCATION "${SDL2_SDLMAIN_LIBRARY}")
214			set(SDL2MAIN_LIBRARIES SDL2::SDL2main_real ${SDL2MAIN_LIBRARIES})
215		endif()
216		if(MINGW)
217			# MinGW requires some additional libraries to appear earlier in the link line.
218			if(SDL2PC_LIBRARIES)
219				# Use pkgconfig-suggested extra libraries if available.
220				list(REMOVE_ITEM SDL2PC_LIBRARIES SDL2main SDL2)
221				set(SDL2MAIN_LIBRARIES ${SDL2PC_LIBRARIES} ${SDL2MAIN_LIBRARIES})
222			else()
223				# fall back to extra libraries specified in pkg-config in
224				# an official binary distro of SDL2 for MinGW I downloaded
225				if(SDL2_MINGW_LIBRARY)
226					set(SDL2MAIN_LIBRARIES ${SDL2_MINGW_LIBRARY} ${SDL2MAIN_LIBRARIES})
227				endif()
228				if(SDL2_MWINDOWS_LIBRARY)
229					set(SDL2MAIN_LIBRARIES ${SDL2_MWINDOWS_LIBRARY} ${SDL2MAIN_LIBRARIES})
230				endif()
231			endif()
232			set_target_properties(SDL2::SDL2main
233				PROPERTIES
234				INTERFACE_COMPILE_DEFINITIONS "main=SDL_main")
235		endif()
236		set_target_properties(SDL2::SDL2main
237			PROPERTIES
238			INTERFACE_LINK_LIBRARIES "${SDL2MAIN_LIBRARIES}")
239	endif()
240	mark_as_advanced(SDL2_ROOT_DIR)
241endif()
242
243mark_as_advanced(SDL2_LIBRARY
244	SDL2_RUNTIME_LIBRARY
245	SDL2_INCLUDE_DIR
246	SDL2_SDLMAIN_LIBRARY
247	SDL2_COCOA_LIBRARY
248	SDL2_MINGW_LIBRARY
249	SDL2_MWINDOWS_LIBRARY)
250