1#
2# Copyright (c) 2008-2017 the Urho3D project.
3#
4# Permission is hereby granted, free of charge, to any person obtaining a copy
5# of this software and associated documentation files (the "Software"), to deal
6# in the Software without restriction, including without limitation the rights
7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8# copies of the Software, and to permit persons to whom the Software is
9# furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be included in
12# all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20# THE SOFTWARE.
21#
22
23# Save the initial values of CC and CXX environment variables
24if (NOT CMAKE_CROSSCOMPILING)
25    set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
26    set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
27endif ()
28
29# Limit the supported build configurations
30set (URHO3D_BUILD_CONFIGURATIONS Release RelWithDebInfo Debug)
31set (DOC_STRING "Specify CMake build configuration (single-configuration generator only), possible values are Release (default), RelWithDebInfo, and Debug")
32if (CMAKE_CONFIGURATION_TYPES)
33    # For multi-configurations generator, such as VS and Xcode
34    set (CMAKE_CONFIGURATION_TYPES ${URHO3D_BUILD_CONFIGURATIONS} CACHE STRING ${DOC_STRING} FORCE)
35    unset (CMAKE_BUILD_TYPE)
36else ()
37    # For single-configuration generator, such as Unix Makefile generator
38    if (CMAKE_BUILD_TYPE STREQUAL "")
39        # If not specified then default to Release
40        set (CMAKE_BUILD_TYPE Release)
41    endif ()
42    set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING ${DOC_STRING} FORCE)
43endif ()
44
45# Define other useful variables not defined by CMake
46if (CMAKE_GENERATOR STREQUAL Xcode)
47    set (XCODE TRUE)
48elseif (CMAKE_GENERATOR STREQUAL Ninja)
49    set (NINJA TRUE)
50elseif (CMAKE_GENERATOR MATCHES Visual)
51    set (VS TRUE)
52endif ()
53
54# Rightfully we could have performed this inside a CMake/iOS toolchain file but we don't have one nor need for one for now
55if (IOS)
56    set (CMAKE_CROSSCOMPILING TRUE)
57    set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -iphoneos -iphonesimulator)
58    set (CMAKE_OSX_SYSROOT iphoneos)    # Set Base SDK to "Latest iOS"
59    # This is a CMake hack in order to make standard CMake check modules that use try_compile() internally work on iOS platform
60    # The injected "flags" are not compiler flags, they are actually CMake variables meant for another CMake subprocess that builds the source file being passed in the try_compile() command
61    # CAVEAT: these injected "flags" must always be kept at the end of the string variable, i.e. when adding more compiler flags later on then those new flags must be prepended in front of these flags instead
62    set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=")
63    if (NOT IOS_SYSROOT)
64        execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   # Obtain iOS sysroot path
65        set (IOS_SYSROOT ${IOS_SYSROOT} CACHE INTERNAL "Path to iOS system root")
66    endif ()
67    set (CMAKE_FIND_ROOT_PATH ${IOS_SYSROOT})
68    set (IPHONEOS_DEPLOYMENT_TARGET "" CACHE STRING "Specify iOS deployment target (iOS platform only); default to latest installed iOS SDK if not specified, the minimum supported target is 3.0 due to constraint from SDL library")
69    if (DEPLOYMENT_TARGET_SAVED AND NOT ${IPHONEOS_DEPLOYMENT_TARGET}: STREQUAL DEPLOYMENT_TARGET_SAVED)
70        string (REPLACE : "" DEPLOYMENT_TARGET_SAVED ${DEPLOYMENT_TARGET_SAVED})
71        set (IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET_SAVED}" CACHE STRING "Specify iOS deployment target (iOS platform only); default to latest installed iOS SDK if not specified, the minimum supported target is 3.0 due to constraint from SDL library" FORCE)
72        message (FATAL_ERROR "IPHONEOS_DEPLOYMENT_TARGET cannot be changed after the initial configuration/generation. "
73            "Auto reverting to its initial value. If you wish to change it then the build tree would have to be regenerated from scratch.")
74    endif ()
75    set (CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${IPHONEOS_DEPLOYMENT_TARGET})
76    set (DEPLOYMENT_TARGET_SAVED ${IPHONEOS_DEPLOYMENT_TARGET}: CACHE INTERNAL "Last known deployment target")    # with sentinel so it does not appear empty even when the default target is used
77    set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
78    # Workaround what appears to be a bug in CMake/Xcode generator, ensure the CMAKE_OSX_DEPLOYMENT_TARGET is set to empty for iOS build
79    set (CMAKE_OSX_DEPLOYMENT_TARGET)
80    unset (CMAKE_OSX_DEPLOYMENT_TARGET CACHE)
81elseif (TVOS)
82    set (CMAKE_CROSSCOMPILING TRUE)
83    set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -appletvos -appletvsimulator)
84    set (CMAKE_OSX_SYSROOT appletvos)    # Set Base SDK to "Latest tvOS"
85    set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=")
86    if (NOT TVOS_SYSROOT)
87        execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE TVOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   # Obtain tvOS sysroot path
88        set (TVOS_SYSROOT ${TVOS_SYSROOT} CACHE INTERNAL "Path to tvOS system root")
89    endif ()
90    set (CMAKE_FIND_ROOT_PATH ${TVOS_SYSROOT})
91    set (APPLETVOS_DEPLOYMENT_TARGET "" CACHE STRING "Specify tvOS deployment target (tvOS platform only); default to latest installed tvOS SDK if not specified")
92    set (CMAKE_XCODE_ATTRIBUTE_APPLETVOS_DEPLOYMENT_TARGET ${APPLETVOS_DEPLOYMENT_TARGET})
93    set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
94    # Just in case it has similar bug for tvOS build
95    set (CMAKE_OSX_DEPLOYMENT_TARGET)
96    unset (CMAKE_OSX_DEPLOYMENT_TARGET CACHE)
97elseif (XCODE)
98    set (CMAKE_OSX_SYSROOT macosx)    # Set Base SDK to "Latest OS X"
99    if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
100        # If not set, set to current running build system OS version by default
101        execute_process (COMMAND sw_vers -productVersion OUTPUT_VARIABLE CURRENT_OSX_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
102        string (REGEX REPLACE ^\([^.]+\\.[^.]+\).* \\1 CMAKE_OSX_DEPLOYMENT_TARGET ${CURRENT_OSX_VERSION})
103        set (CMAKE_OSX_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET} CACHE STRING "Specify macOS deployment target (macOS platform only); default to current running macOS if not specified, the minimum supported target is 10.5 due to constraint from SDL library")
104    endif ()
105    if (DEPLOYMENT_TARGET_SAVED AND NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL DEPLOYMENT_TARGET_SAVED)
106        set (CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET_SAVED} CACHE STRING "Specify macOS deployment target (macOS platform only); default to current running macOS if not specified, the minimum supported target is 10.5 due to constraint from SDL library" FORCE)
107        message (FATAL_ERROR "CMAKE_OSX_DEPLOYMENT_TARGET cannot be changed after the initial configuration/generation. "
108            "Auto reverting to its initial value. If you wish to change it then the build tree would have to be regenerated from scratch.")
109    endif ()
110    set (DEPLOYMENT_TARGET_SAVED ${CMAKE_OSX_DEPLOYMENT_TARGET} CACHE INTERNAL "Last known deployment target")
111endif ()
112
113include (CheckHost)
114include (CheckCompilerToolchain)
115
116# Extra linker flags for linking against indirect dependencies (linking shared lib with dependencies)
117if (RPI)
118    # Extra linker flags for Raspbian because it installs VideoCore libraries in the "/opt/vc/lib" directory (no harm in doing so for other distros)
119    set (INDIRECT_DEPS_EXE_LINKER_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} -Wl,-rpath-link,\"${CMAKE_SYSROOT}/opt/vc/lib\"")      # CMAKE_SYSROOT is empty when not cross-compiling
120elseif (APPLE AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0.0)
121    set (INDIRECT_DEPS_EXE_LINKER_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} -Wl,-no_weak_imports")
122endif ()
123if (ARM AND CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
124    # Cannot do this in the toolchain file because CMAKE_LIBRARY_ARCHITECTURE is not yet defined when CMake is processing toolchain file
125    set (INDIRECT_DEPS_EXE_LINKER_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} -Wl,-rpath-link,\"${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}\":\"${CMAKE_SYSROOT}/lib/${CMAKE_LIBRARY_ARCHITECTURE}\"")
126endif ()
127set (CMAKE_REQUIRED_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} ${CMAKE_REQUIRED_FLAGS}")
128set (CMAKE_EXE_LINKER_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
129
130# Define all supported build options
131include (CMakeDependentOption)
132option (URHO3D_C++11 "Enable C++11 standard")
133cmake_dependent_option (IOS "Setup build for iOS platform" FALSE "XCODE" FALSE)
134cmake_dependent_option (TVOS "Setup build for tvOS platform" FALSE "XCODE" FALSE)
135cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain" "${NATIVE_64BIT}" "NOT MSVC AND NOT ANDROID AND NOT (ARM AND NOT IOS) AND NOT WEB AND NOT POWERPC" "${NATIVE_64BIT}")     # Intentionally only enable the option for iOS but not for tvOS as the latter is 64-bit only
136option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
137option (URHO3D_IK "Enable inverse kinematics support" TRUE)
138option (URHO3D_LUA "Enable additional Lua scripting support" TRUE)
139option (URHO3D_NAVIGATION "Enable navigation support" TRUE)
140# Urho's Network subsystem depends on kNet library which uses C++ exceptions feature
141cmake_dependent_option (URHO3D_NETWORK "Enable networking support" TRUE "NOT WEB AND EXCEPTIONS" FALSE)
142option (URHO3D_PHYSICS "Enable physics support" TRUE)
143option (URHO3D_URHO2D "Enable 2D graphics and physics support" TRUE)
144option (URHO3D_WEBP "Enable WebP support" TRUE)
145if (ARM AND NOT ANDROID AND NOT RPI AND NOT APPLE)
146    set (ARM_ABI_FLAGS "" CACHE STRING "Specify ABI compiler flags (ARM on Linux platform only); e.g. Orange-Pi Mini 2 could use '-mcpu=cortex-a7 -mfpu=neon-vfpv4'")
147endif ()
148if ((RPI AND "${RPI_ABI}" MATCHES NEON) OR (ARM AND (APPLE OR URHO3D_64BIT OR "${ARM_ABI_FLAGS}" MATCHES neon)))    # Stringify in case RPI_ABI/ARM_ABI_FLAGS is not set explicitly
149    # TODO: remove this logic when the compiler flags are set in each toolchain file, such that the CheckCompilerToolchain can perform the check automatically
150    set (NEON 1)
151endif ()
152# For Raspbery Pi, find Broadcom VideoCore IV firmware
153if (RPI)
154    # TODO: this logic is earmarked to be moved into SDL's CMakeLists.txt when refactoring the library dependency handling
155    find_package (VideoCore REQUIRED)
156    include_directories (SYSTEM ${VIDEOCORE_INCLUDE_DIRS})
157    link_directories (${VIDEOCORE_LIBRARY_DIRS})
158endif ()
159if (CMAKE_PROJECT_NAME STREQUAL Urho3D)
160    set (URHO3D_LIB_TYPE STATIC CACHE STRING "Specify Urho3D library type, possible values are STATIC (default), SHARED, and MODULE; the last value is available for Emscripten only")
161    # Non-Windows platforms always use OpenGL, the URHO3D_OPENGL variable will always be forced to TRUE, i.e. it is not an option at all
162    # Windows platform has URHO3D_OPENGL as an option, MSVC compiler default to FALSE (i.e. prefers Direct3D) while MinGW compiler default to TRUE
163    if (MINGW)
164        set (DEFAULT_OPENGL TRUE)
165    endif ()
166    cmake_dependent_option (URHO3D_OPENGL "Use OpenGL instead of Direct3D (Windows platform only)" "${DEFAULT_OPENGL}" WIN32 TRUE)
167    # On Windows platform Direct3D11 can be optionally chosen
168    # Using Direct3D11 on non-MSVC compiler may require copying and renaming Microsoft official libraries (.lib to .a), else link failures or non-functioning graphics may result
169    cmake_dependent_option (URHO3D_D3D11 "Use Direct3D11 instead of Direct3D9 (Windows platform only); overrides URHO3D_OPENGL option" FALSE "WIN32" FALSE)
170    if (MINGW AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.1)
171        if (NOT DEFINED URHO3D_SSE)     # Only give the warning once during initial configuration
172            # Certain MinGW versions fail to compile SSE code. This is the initial guess for known "bad" version range, and can be tightened later
173            message (WARNING "Disabling SSE by default due to MinGW version. It is recommended to upgrade to MinGW with GCC >= 4.9.1. "
174                "You can also try to re-enable SSE with CMake option -DURHO3D_SSE=1, but this may result in compile errors.")
175        endif ()
176    endif ()
177    if (X86 OR WEB)
178        # It is not possible to turn SSE off on 64-bit MSVC and it appears it is also not able to do so safely on 64-bit GCC
179        cmake_dependent_option (URHO3D_SSE "Enable SSE/SSE2 instruction set (32-bit Web and Intel platforms only, including Android on Intel Atom); default to true on Intel and false on Web platform; the effective SSE level could be higher, see also URHO3D_DEPLOYMENT_TARGET and CMAKE_OSX_DEPLOYMENT_TARGET build options" "${HAVE_SSE2}" "NOT URHO3D_64BIT" TRUE)
180    endif ()
181    cmake_dependent_option (URHO3D_3DNOW "Enable 3DNow! instruction set (Linux platform only); should only be used for older CPU with (legacy) 3DNow! support" "${HAVE_3DNOW}" "X86 AND CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT URHO3D_SSE" FALSE)
182    cmake_dependent_option (URHO3D_MMX "Enable MMX instruction set (32-bit Linux platform only); the MMX is effectively enabled when 3DNow! or SSE is enabled; should only be used for older CPU with MMX support" "${HAVE_MMX}" "X86 AND CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT URHO3D_64BIT AND NOT URHO3D_SSE AND NOT URHO3D_3DNOW" FALSE)
183    # For completeness sake - this option is intentionally not documented as we do not officially support PowerPC (yet)
184    cmake_dependent_option (URHO3D_ALTIVEC "Enable AltiVec instruction set (PowerPC only)" "${HAVE_ALTIVEC}" POWERPC FALSE)
185    cmake_dependent_option (URHO3D_LUAJIT "Enable Lua scripting support using LuaJIT (check LuaJIT's CMakeLists.txt for more options)" FALSE "NOT WEB" FALSE)
186    cmake_dependent_option (URHO3D_LUAJIT_AMALG "Enable LuaJIT amalgamated build (LuaJIT only)" FALSE URHO3D_LUAJIT FALSE)
187    cmake_dependent_option (URHO3D_SAFE_LUA "Enable Lua C++ wrapper safety checks (Lua/LuaJIT only)" FALSE URHO3D_LUA FALSE)
188    if (NOT CMAKE_BUILD_TYPE STREQUAL Release AND NOT CMAKE_CONFIGURATION_TYPES)
189        set (DEFAULT_LUA_RAW TRUE)
190    endif ()
191    cmake_dependent_option (URHO3D_LUA_RAW_SCRIPT_LOADER "Prefer loading raw script files from the file system before falling back on Urho3D resource cache. Useful for debugging (e.g. breakpoints), but less performant (Lua/LuaJIT only)" "${DEFAULT_LUA_RAW}" URHO3D_LUA FALSE)
192    option (URHO3D_SAMPLES "Build sample applications" TRUE)
193    option (URHO3D_UPDATE_SOURCE_TREE "Enable commands to copy back some of the generated build artifacts from build tree to source tree to facilitate devs to push them as part of a commit (for library devs with push right only)")
194    option (URHO3D_BINDINGS "Enable API binding generation support for script subystems")
195    cmake_dependent_option (URHO3D_CLANG_TOOLS "Build Clang tools (native on host system only)" FALSE "NOT CMAKE_CROSSCOMPILING" FALSE)
196    mark_as_advanced (URHO3D_UPDATE_SOURCE_TREE URHO3D_BINDINGS URHO3D_CLANG_TOOLS)
197    cmake_dependent_option (URHO3D_TOOLS "Build tools (native, RPI, and ARM on Linux only)" TRUE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB" FALSE)
198    cmake_dependent_option (URHO3D_EXTRAS "Build extras (native, RPI, and ARM on Linux only)" FALSE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB" FALSE)
199    option (URHO3D_DOCS "Generate documentation as part of normal build")
200    option (URHO3D_DOCS_QUIET "Generate documentation as part of normal build, suppress generation process from sending anything to stdout")
201    option (URHO3D_PCH "Enable PCH support" TRUE)
202    cmake_dependent_option (URHO3D_DATABASE_ODBC "Enable Database support with ODBC, requires vendor-specific ODBC driver" FALSE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB;NOT MSVC OR NOT MSVC_VERSION VERSION_LESS 1900" FALSE)
203    option (URHO3D_DATABASE_SQLITE "Enable Database support with SQLite embedded")
204    # Enable file watcher support for automatic resource reloads by default.
205    option (URHO3D_FILEWATCHER "Enable filewatcher support" TRUE)
206    option (URHO3D_TESTING "Enable testing support")
207    # By default this option is off (i.e. we use the MSVC dynamic runtime), this can be switched on if using Urho3D as a STATIC library
208    cmake_dependent_option (URHO3D_STATIC_RUNTIME "Use static C/C++ runtime libraries and eliminate the need for runtime DLLs installation (VS only)" FALSE "MSVC" FALSE)
209    if (((URHO3D_LUA AND NOT URHO3D_LUAJIT) OR URHO3D_DATABASE_SQLITE) AND NOT ANDROID AND NOT IOS AND NOT TVOS AND NOT WEB AND NOT WIN32)
210        # Find GNU Readline development library for Lua interpreter and SQLite's isql
211        find_package (Readline)
212    endif ()
213    if (CPACK_SYSTEM_NAME STREQUAL Linux)
214        cmake_dependent_option (URHO3D_USE_LIB64_RPM "Enable 64-bit RPM CPack generator using /usr/lib64 and disable all other generators (Debian-based host only)" FALSE "URHO3D_64BIT AND NOT HAS_LIB64" FALSE)
215        cmake_dependent_option (URHO3D_USE_LIB_DEB "Enable 64-bit DEB CPack generator using /usr/lib and disable all other generators (Redhat-based host only)" FALSE "URHO3D_64BIT AND HAS_LIB64" FALSE)
216    endif ()
217    # Set to search in 'lib' or 'lib64' based on the chosen ABI
218    if (NOT CMAKE_HOST_WIN32)
219        set_property (GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ${URHO3D_64BIT})
220    endif ()
221else ()
222    set (URHO3D_LIB_TYPE "" CACHE STRING "Specify Urho3D library type, possible values are STATIC (default), SHARED, and MODULE; the last value is available for Emscripten only")
223    set (URHO3D_HOME "" CACHE PATH "Path to Urho3D build tree or SDK installation location (downstream project only)")
224    if (URHO3D_PCH OR URHO3D_UPDATE_SOURCE_TREE OR URHO3D_TOOLS)
225        # Just reference it to suppress "unused variable" CMake warning on downstream projects using this CMake module
226    endif ()
227    if (CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
228        set (URHO3D_SSE ${HAVE_SSE2})
229    else ()
230        # All Urho3D downstream projects require Urho3D library, so find Urho3D library here now
231        find_package (Urho3D REQUIRED)
232        include_directories (${URHO3D_INCLUDE_DIRS})
233    endif ()
234endif ()
235cmake_dependent_option (URHO3D_PACKAGING "Enable resources packaging support" FALSE "NOT WEB" TRUE)
236# Enable profiling by default. If disabled, autoprofileblocks become no-ops and the Profiler subsystem is not instantiated.
237option (URHO3D_PROFILING "Enable profiling support" TRUE)
238# Enable logging by default. If disabled, LOGXXXX macros become no-ops and the Log subsystem is not instantiated.
239option (URHO3D_LOGGING "Enable logging support" TRUE)
240# Enable threading by default, except for Emscripten because its thread support is yet experimental
241if (NOT WEB)
242    set (THREADING_DEFAULT TRUE)
243endif ()
244option (URHO3D_THREADING "Enable thread support, on Web platform default to 0, on other platforms default to 1" ${THREADING_DEFAULT})
245if (URHO3D_TESTING)
246    if (WEB)
247        set (DEFAULT_TIMEOUT 10)
248        if (EMSCRIPTEN)
249            set (EMSCRIPTEN_EMRUN_BROWSER firefox CACHE STRING "Specify the particular browser to be spawned by emrun during testing (Emscripten only), use 'emrun --list_browsers' command to get the list of possible values")
250        endif ()
251    else ()
252        set (DEFAULT_TIMEOUT 5)
253    endif ()
254    set (URHO3D_TEST_TIMEOUT ${DEFAULT_TIMEOUT} CACHE STRING "Number of seconds to test run the executables (when testing support is enabled only), default to 10 on Web platform and 5 on other platforms")
255else ()
256    unset (URHO3D_TEST_TIMEOUT CACHE)
257    if (EMSCRIPTEN_EMRUN_BROWSER)   # Suppress unused variable warning at the same time
258        unset (EMSCRIPTEN_EMRUN_BROWSER CACHE)
259    endif ()
260endif ()
261# Structured exception handling and minidumps on MSVC only
262cmake_dependent_option (URHO3D_MINIDUMPS "Enable minidumps on crash (VS only)" TRUE "MSVC" FALSE)
263# By default Windows platform setups main executable as Windows application with WinMain() as entry point
264cmake_dependent_option (URHO3D_WIN32_CONSOLE "Use console main() instead of WinMain() as entry point when setting up Windows executable targets (Windows platform only)" FALSE "WIN32" FALSE)
265cmake_dependent_option (URHO3D_MACOSX_BUNDLE "Use MACOSX_BUNDLE when setting up macOS executable targets (Xcode/macOS platform only)" FALSE "XCODE AND NOT ARM" FALSE)
266if (CMAKE_CROSSCOMPILING AND NOT ANDROID AND NOT APPLE)
267    set (URHO3D_SCP_TO_TARGET "" CACHE STRING "Use scp to transfer executables to target system (RPI and generic ARM cross-compiling build only), SSH digital key must be setup first for this to work, typical value has a pattern of usr@tgt:remote-loc")
268else ()
269    unset (URHO3D_SCP_TO_TARGET CACHE)
270endif ()
271if (ANDROID)
272    set (ANDROID TRUE CACHE INTERNAL "Setup build for Android platform")
273    cmake_dependent_option (ANDROID_NDK_GDB "Enable ndk-gdb for debugging (Android platform only)" FALSE "CMAKE_BUILD_TYPE STREQUAL Debug" FALSE)
274else ()
275    unset (ANDROID_NDK_GDB CACHE)
276endif ()
277if (MINGW AND CMAKE_CROSSCOMPILING)
278    set (MINGW_PREFIX "" CACHE STRING "Prefix path to MinGW cross-compiler tools (MinGW cross-compiling build only)")
279    set (MINGW_SYSROOT "" CACHE PATH "Path to MinGW system root (MinGW only); should only be used when the system root could not be auto-detected")
280    # When cross-compiling then we are most probably in Unix-alike host environment which should not have problem to handle long include dirs
281    # This change is required to keep ccache happy because it does not like the CMake generated include response file
282    foreach (lang C CXX)
283        foreach (cat OBJECTS INCLUDES)
284            unset (CMAKE_${lang}_USE_RESPONSE_FILE_FOR_${cat})
285        endforeach ()
286    endforeach ()
287endif ()
288if (RPI)
289    if (NOT RPI_SUPPORTED_ABIS)
290        set (RPI_SUPPORTED_ABIS armeabi-v6)
291        if (CMAKE_CROSSCOMPILING)
292            # We have no way to know for sure so just give all the available options to user
293            list (APPEND RPI_SUPPORTED_ABIS armeabi-v7a "armeabi-v7a with NEON" "armeabi-v7a with VFPV4")
294        else ()
295            # If not cross-compiling then we should be on the host system (device) itself, so below command is safe to be executed
296            execute_process (COMMAND uname -m OUTPUT_VARIABLE HOST_MACHINE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
297            if (HOST_MACHINE MATCHES ^armv7)
298                list (APPEND RPI_SUPPORTED_ABIS armeabi-v7a "armeabi-v7a with NEON" "armeabi-v7a with VFPV4")
299                if (NOT RPI_ABI)
300                    set (RPI_ABI armeabi-v7a)   # Set default to this specific target device
301                endif ()
302            endif ()
303        endif ()
304        set (RPI_SUPPORTED_ABIS ${RPI_SUPPORTED_ABIS} CACHE INTERNAL "Supported target ABIs for RPI build")
305    endif ()
306    if (CMAKE_CROSSCOMPILING)
307        set (RPI_PREFIX "" CACHE STRING "Prefix path to Raspberry Pi cross-compiler tools (RPI cross-compiling build only)")
308        set (RPI_SYSROOT "" CACHE PATH "Path to Raspberry Pi system root (RPI cross-compiling build only)")
309    endif ()
310    if (RPI_ABI)
311        list (FIND RPI_SUPPORTED_ABIS ${RPI_ABI} RPI_ABI_FOUND_INDEX)
312        if (RPI_ABI_FOUND_INDEX EQUAL -1)
313            string (REPLACE ";" "\", \"" PRINTABLE_RPI_SUPPORTED_ABIS "${RPI_SUPPORTED_ABIS}")  # Stringify for string replace to work
314            if (NOT CMAKE_CROSSCOMPILING)
315                set (MSG_STR " by this Raspberry Pi device")
316            endif ()
317            message (FATAL_ERROR "Specified RPI_ABI = \"${RPI_ABI}\" is not supported${MSG_STR}. Supported values are: \"${PRINTABLE_RPI_SUPPORTED_ABIS}\".")
318        endif ()
319    else ()
320        set (RPI_ABI armeabi-v6)
321    endif ()
322    set (RPI_ABI ${RPI_ABI} CACHE STRING "Specify target ABI (RPI platform only), possible values are armeabi-v6 (default for RPI 1), armeabi-v7a (default for RPI 2), armeabi-v7a with NEON, and armeabi-v7a with VFPV4" FORCE)
323endif ()
324if (EMSCRIPTEN)     # CMAKE_CROSSCOMPILING is always true for Emscripten
325    set (MODULE MODULE)
326    set (EMSCRIPTEN_ROOT_PATH "" CACHE PATH "Root path to Emscripten cross-compiler tools (Emscripten only)")
327    set (EMSCRIPTEN_SYSROOT "" CACHE PATH "Path to Emscripten system root (Emscripten only)")
328    cmake_dependent_option (EMSCRIPTEN_WASM "Enable Binaryen support to generate output to WASM (WebAssembly) format (Emscripten only)" FALSE "NOT EMSCRIPTEN_EMCC_VERSION VERSION_LESS 1.37.3" FALSE)
329    # Currently Emscripten does not support memory growth with MODULE library type
330    if (URHO3D_LIB_TYPE STREQUAL MODULE)
331        set (DEFAULT_MEMORY_GROWTH FALSE)
332    else ()
333        set (DEFAULT_MEMORY_GROWTH TRUE)
334    endif ()
335    cmake_dependent_option (EMSCRIPTEN_ALLOW_MEMORY_GROWTH "Enable memory growing based on application demand when targeting asm.js, it is not set by default due to performance penalty (Emscripten with STATIC or SHARED library type only)" FALSE "NOT EMSCRIPTEN_WASM AND NOT URHO3D_LIB_TYPE STREQUAL MODULE" ${DEFAULT_MEMORY_GROWTH})   # Allow memory growth by default when targeting WebAssembly since there is no performance penalty as in asm.js mode
336    math (EXPR EMSCRIPTEN_TOTAL_MEMORY "128 * 1024 * 1024")
337    set (EMSCRIPTEN_TOTAL_MEMORY ${EMSCRIPTEN_TOTAL_MEMORY} CACHE STRING "Specify the total size of memory to be used (Emscripten only); default to 128 MB, must be in multiple of 64 KB when targeting WebAssembly and in multiple of 16 MB when targeting asm.js")
338    cmake_dependent_option (EMSCRIPTEN_SHARE_DATA "Enable sharing data file support (Emscripten only)" FALSE "NOT URHO3D_LIB_TYPE STREQUAL MODULE" TRUE)
339endif ()
340# Constrain the build option values in cmake-gui, if applicable
341set_property (CACHE URHO3D_LIB_TYPE PROPERTY STRINGS STATIC SHARED ${MODULE})
342if (NOT CMAKE_CONFIGURATION_TYPES)
343    set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${URHO3D_BUILD_CONFIGURATIONS})
344endif ()
345if (RPI)
346    set_property (CACHE RPI_ABI PROPERTY STRINGS ${RPI_SUPPORTED_ABIS})
347endif ()
348# Handle mutually exclusive options and implied options
349if (URHO3D_D3D11)
350    set (URHO3D_OPENGL 0)
351    unset (URHO3D_OPENGL CACHE)
352endif ()
353if (URHO3D_DATABASE_ODBC)
354    set (URHO3D_DATABASE_SQLITE 0)
355    unset (URHO3D_DATABASE_SQLITE CACHE)
356endif ()
357if (URHO3D_DATABASE_SQLITE OR URHO3D_DATABASE_ODBC)
358    set (URHO3D_DATABASE 1)
359endif ()
360if (URHO3D_LUAJIT)
361    set (JIT JIT)
362    set (URHO3D_LUA 1)
363endif ()
364
365# Union all the sysroot variables into one so it can be referred to generically later
366set (SYSROOT ${CMAKE_SYSROOT} ${MINGW_SYSROOT} ${IOS_SYSROOT} ${TVOS_SYSROOT} CACHE INTERNAL "Path to system root of the cross-compiling target")  # SYSROOT is empty for native build
367
368# Clang tools building
369if (URHO3D_CLANG_TOOLS OR URHO3D_BINDINGS)
370    # Ensure LLVM/Clang is installed
371    find_program (LLVM_CONFIG NAMES llvm-config llvm-config-64 llvm-config-32 HINTS $ENV{LLVM_CLANG_ROOT}/bin DOC "LLVM config tool" NO_CMAKE_FIND_ROOT_PATH)
372    if (NOT LLVM_CONFIG)
373        message (FATAL_ERROR "Could not find LLVM/Clang installation")
374    endif ()
375endif ()
376if (URHO3D_CLANG_TOOLS)
377    # Require C++11 standard and no precompiled-header
378    set (URHO3D_C++11 1)
379    set (URHO3D_PCH 0)
380    set (URHO3D_LIB_TYPE SHARED)
381    # Set build options that would maximise the AST of Urho3D library
382    foreach (OPT
383            URHO3D_ANGELSCRIPT
384            URHO3D_DATABASE_SQLITE
385            URHO3D_FILEWATCHER
386            URHO3D_IK
387            URHO3D_LOGGING
388            URHO3D_LUA
389            URHO3D_NAVIGATION
390            URHO3D_NETWORK
391            URHO3D_PHYSICS
392            URHO3D_PROFILING
393            URHO3D_URHO2D)
394        set (${OPT} 1)
395    endforeach ()
396    foreach (OPT URHO3D_TESTING URHO3D_LUAJIT URHO3D_DATABASE_ODBC)
397        set (${OPT} 0)
398    endforeach ()
399endif ()
400
401# Coverity scan does not support PCH
402if ($ENV{COVERITY_SCAN_BRANCH})
403    set (URHO3D_PCH 0)
404endif ()
405
406# Enable testing
407if (URHO3D_TESTING)
408    enable_testing ()
409endif ()
410
411# Default library type is STATIC
412if (URHO3D_LIB_TYPE)
413    string (TOUPPER ${URHO3D_LIB_TYPE} URHO3D_LIB_TYPE)
414endif ()
415if (NOT URHO3D_LIB_TYPE STREQUAL SHARED AND NOT URHO3D_LIB_TYPE STREQUAL MODULE)
416    set (URHO3D_LIB_TYPE STATIC)
417    if (MSVC)
418        # This define will be baked into the export header for MSVC compiler
419        set (URHO3D_STATIC_DEFINE 1)
420    else ()
421        # Only define it on the fly when necessary (both SHARED and STATIC libs can coexist) for other compiler toolchains
422        add_definitions (-DURHO3D_STATIC_DEFINE)
423    endif ()
424endif ()
425
426# Force C++11 standard (required by the generic bindings generation) if using AngelScript on Web and 64-bit ARM platforms
427if (URHO3D_ANGELSCRIPT AND (EMSCRIPTEN OR (ARM AND URHO3D_64BIT)))
428    set (URHO3D_C++11 1)
429endif ()
430
431# Force C++11 standard (required by nanodbc library) if using ODBC
432if (URHO3D_DATABASE_ODBC)
433    find_package (ODBC REQUIRED)
434    set (URHO3D_C++11 1)
435endif ()
436
437# Define preprocessor macros (for building the Urho3D library) based on the configured build options
438foreach (OPT
439        URHO3D_ANGELSCRIPT
440        URHO3D_DATABASE
441        URHO3D_FILEWATCHER
442        URHO3D_IK
443        URHO3D_LOGGING
444        URHO3D_LUA
445        URHO3D_MINIDUMPS
446        URHO3D_NAVIGATION
447        URHO3D_NETWORK
448        URHO3D_PHYSICS
449        URHO3D_PROFILING
450        URHO3D_THREADING
451        URHO3D_URHO2D
452        URHO3D_WEBP
453        URHO3D_WIN32_CONSOLE)
454    if (${OPT})
455        add_definitions (-D${OPT})
456    endif ()
457endforeach ()
458
459# TODO: The logic below is earmarked to be moved into SDL's CMakeLists.txt when refactoring the library dependency handling, until then ensure the DirectX package is not being searched again in external projects such as when building LuaJIT library
460if (WIN32 AND NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
461    set (DIRECTX_REQUIRED_COMPONENTS)
462    set (DIRECTX_OPTIONAL_COMPONENTS DInput DSound XAudio2 XInput)
463    if (NOT URHO3D_OPENGL)
464        if (URHO3D_D3D11)
465            list (APPEND DIRECTX_REQUIRED_COMPONENTS D3D11)
466        else ()
467            list (APPEND DIRECTX_REQUIRED_COMPONENTS D3D)
468        endif ()
469    endif ()
470    find_package (DirectX REQUIRED ${DIRECTX_REQUIRED_COMPONENTS} OPTIONAL_COMPONENTS ${DIRECTX_OPTIONAL_COMPONENTS})
471    if (DIRECTX_FOUND)
472        include_directories (SYSTEM ${DIRECTX_INCLUDE_DIRS})   # These variables may be empty when WinSDK or MinGW is being used
473        link_directories (${DIRECTX_LIBRARY_DIRS})
474    endif ()
475endif ()
476
477# Platform and compiler specific options
478if (URHO3D_C++11)
479    add_definitions (-DURHO3D_CXX11)   # Note the define is NOT 'URHO3D_C++11'!
480    if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
481        # Use gnu++11/gnu++0x instead of c++11/c++0x as the latter does not work as expected when cross compiling
482        if (VERIFIED_SUPPORTED_STANDARD)
483            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=${VERIFIED_SUPPORTED_STANDARD}")
484        else ()
485            foreach (STANDARD gnu++11 gnu++0x)  # Fallback to gnu++0x on older GCC version
486                execute_process (COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_CXX_COMPILER} -std=${STANDARD} -E - RESULT_VARIABLE GCC_EXIT_CODE OUTPUT_QUIET ERROR_QUIET)
487                if (GCC_EXIT_CODE EQUAL 0)
488                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=${STANDARD}")
489                    set (VERIFIED_SUPPORTED_STANDARD ${STANDARD} CACHE INTERNAL "GNU extension of C++11 standard that is verified to be supported by the chosen compiler")
490                    break ()
491                endif ()
492            endforeach ()
493            if (NOT GCC_EXIT_CODE EQUAL 0)
494                message (FATAL_ERROR "Your GCC version ${CMAKE_CXX_COMPILER_VERSION} is too old to enable C++11 standard")
495            endif ()
496        endif ()
497    elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
498        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
499    elseif (MSVC80)
500        message (FATAL_ERROR "Your MSVC version is too told to enable C++11 standard")
501    endif ()
502endif ()
503if (APPLE)
504    if (IOS)
505        # iOS-specific setup
506        add_definitions (-DIOS)
507        if (URHO3D_64BIT)
508            if (DEFINED ENV{XCODE_64BIT_ONLY})                  # This environment variable is set automatically when ccache is just being cleared in Travis CI VM
509                set (CMAKE_OSX_ARCHITECTURES "arm64 x86_64")    # This is a hack to temporarily only build 64-bit archs to reduce overall build time for one build
510            else ()
511                set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD))
512            endif ()
513        else ()
514            # This is a legacy option and should not be used as we are phasing out 32-bit only mode
515            set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
516        endif ()
517    elseif (TVOS)
518        # tvOS-specific setup
519        add_definitions (-DTVOS)
520        set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD))
521    else ()
522        if (XCODE)
523            # macOS-specific setup
524            if (URHO3D_64BIT)
525                if (URHO3D_UNIVERSAL)
526                    # This is a legacy option and should not be used as we are phasing out macOS universal binary mode
527                    set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_64_BIT))
528                else ()
529                    set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD))
530                endif ()
531            else ()
532                # This is a legacy option and should not be used as we are phasing out 32-bit only mode
533                set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
534            endif ()
535        endif ()
536    endif ()
537    # Common macOS, iOS, and tvOS bundle setup
538    if (URHO3D_MACOSX_BUNDLE OR (APPLE AND ARM))
539        # Only set the bundle properties to its default when they are not explicitly specified by user
540        if (NOT MACOSX_BUNDLE_GUI_IDENTIFIER)
541            set (MACOSX_BUNDLE_GUI_IDENTIFIER com.github.urho3d.\${PRODUCT_NAME:rfc1034identifier:lower})
542        endif ()
543        if (NOT MACOSX_BUNDLE_BUNDLE_NAME)
544            set (MACOSX_BUNDLE_BUNDLE_NAME \${PRODUCT_NAME})
545        endif ()
546    endif ()
547endif ()
548if (MSVC)
549    # VS-specific setup
550    add_definitions (-D_CRT_SECURE_NO_WARNINGS)
551    if (URHO3D_STATIC_RUNTIME)
552        set (RELEASE_RUNTIME /MT)
553        set (DEBUG_RUNTIME /MTd)
554    endif ()
555    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
556    set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEBUG_RUNTIME}")
557    set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} ${RELEASE_RUNTIME} /fp:fast /Zi /GS-")
558    set (CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELWITHDEBINFO})
559    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
560    set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_RUNTIME}")
561    set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_RUNTIME} /fp:fast /Zi /GS- /D _SECURE_SCL=0")
562    set (CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
563    # In Visual Studio, SSE2 flag is redundant if already compiling as 64bit; it is already the default for VS2012 (onward) on 32bit
564    # Instead, we must turn SSE/SSE2 off explicitly if user really intends to turn it off
565    if (URHO3D_SSE)
566        if (NOT URHO3D_64BIT AND MSVC_VERSION LESS 1700)
567            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:SSE2")
568            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
569        endif ()
570    else ()
571        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:IA32")
572        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:IA32")
573    endif ()
574    set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF /DEBUG")
575    set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
576else ()
577    # GCC/Clang-specific setup
578    set (CMAKE_CXX_VISIBILITY_PRESET hidden)
579    set (CMAKE_VISIBILITY_INLINES_HIDDEN true)
580    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof")
581    if (NOT ANDROID)    # Most of the flags are already setup in Android toolchain file
582        if (ARM AND CMAKE_SYSTEM_NAME STREQUAL Linux)
583            # Common compiler flags for aarch64-linux-gnu and arm-linux-gnueabihf, we do not support ARM on Windows for now
584            set (ARM_CFLAGS "${ARM_CFLAGS} -fsigned-char -pipe")
585            if (NOT URHO3D_64BIT)
586                # We only support armhf distros, so turn on hard-float by default
587                set (ARM_CFLAGS "${ARM_CFLAGS} -mfloat-abi=hard -Wno-psabi")
588            endif ()
589            # The configuration is done here instead of in CMake toolchain file because we also support native build which does not use toolchain file at all
590            if (RPI)
591                # RPI-specific setup
592                add_definitions (-DRPI)
593                if (RPI_ABI MATCHES ^armeabi-v7a)
594                    set (ARM_CFLAGS "${ARM_CFLAGS} -mcpu=cortex-a7")
595                    if (RPI_ABI MATCHES NEON)
596                        set (ARM_CFLAGS "${ARM_CFLAGS} -mfpu=neon-vfpv4")
597                    elseif (RPI_ABI MATCHES VFPV4)
598                        set (ARM_CFLAGS "${ARM_CFLAGS} -mfpu=vfpv4")
599                    else ()
600                        set (ARM_CFLAGS "${ARM_CFLAGS} -mfpu=vfpv4-d16")
601                    endif ()
602                else ()
603                    set (ARM_CFLAGS "${ARM_CFLAGS} -mcpu=arm1176jzf-s -mfpu=vfp")
604                endif ()
605            else ()
606                # Generic ARM-specific setup
607                add_definitions (-DGENERIC_ARM)
608                if (URHO3D_64BIT)
609                    # aarch64 has only one valid arch so far
610                    set (ARM_CFLAGS "${ARM_CFLAGS} -march=armv8-a")
611                elseif (URHO3D_ANGELSCRIPT)
612                    # Angelscript seems to fail to compile using Thumb states, so force to use ARM states by default
613                    set (ARM_CFLAGS "${ARM_CFLAGS} -marm")
614                endif ()
615                if (ARM_ABI_FLAGS)
616                    # Instead of guessing all the possible ABIs, user would have to specify the ABI compiler flags explicitly via ARM_ABI_FLAGS build option
617                    set (ARM_CFLAGS "${ARM_CFLAGS} ${ARM_ABI_FLAGS}")
618                endif ()
619            endif ()
620            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM_CFLAGS}")
621            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM_CFLAGS}")
622        else ()
623            if (URHO3D_SSE AND NOT XCODE AND NOT WEB)
624                # This may influence the effective SSE level when URHO3D_SSE is on as well
625                set (URHO3D_DEPLOYMENT_TARGET native CACHE STRING "Specify the minimum CPU type on which the target binaries are to be deployed (non-ARM platform only), see GCC/Clang's -march option for possible values; Use 'generic' for targeting a wide range of generic processors")
626                if (NOT URHO3D_DEPLOYMENT_TARGET STREQUAL generic)
627                    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${URHO3D_DEPLOYMENT_TARGET}")
628                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${URHO3D_DEPLOYMENT_TARGET}")
629                endif ()
630            endif ()
631            # We don't add these flags directly here for Xcode because we support Mach-O universal binary build
632            # The compiler flags will be added later conditionally when the effective arch is i386 during build time (using XCODE_ATTRIBUTE target property)
633            if (NOT XCODE)
634                if (NOT URHO3D_64BIT)
635                    # Not the compiler native ABI, this could only happen on multilib-capable compilers
636                    if (NATIVE_64BIT)
637                        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
638                        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
639                    endif ()
640                    # The effective SSE level could be higher, see also URHO3D_DEPLOYMENT_TARGET and CMAKE_OSX_DEPLOYMENT_TARGET build options
641                    # The -mfpmath=sse is not set in global scope but it may be set in local scope when building LuaJIT sub-library for x86 arch
642                    if (URHO3D_SSE)
643                        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2")
644                        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse -msse2")
645                    endif ()
646                endif ()
647                if (NOT URHO3D_SSE)
648                    if (URHO3D_64BIT OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
649                        # Clang enables SSE support for i386 ABI by default, so use the '-mno-sse' compiler flag to nullify that and make it consistent with GCC
650                        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-sse")
651                        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-sse")
652                    endif ()
653                    if (URHO3D_MMX)
654                        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmmx")
655                        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmmx")
656                    endif ()
657                    if (URHO3D_3DNOW)
658                        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m3dnow")
659                        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m3dnow")
660                    endif ()
661                endif ()
662                # For completeness sake only as we do not support PowerPC (yet)
663                if (URHO3D_ALTIVEC)
664                    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maltivec")
665                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maltivec")
666                endif ()
667            endif ()
668        endif ()
669        if (WEB)
670            if (EMSCRIPTEN)
671                # Emscripten-specific setup
672                set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-warn-absolute-paths -Wno-unknown-warning-option")
673                set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-warn-absolute-paths -Wno-unknown-warning-option")
674                if (URHO3D_THREADING)
675                    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s USE_PTHREADS=1")
676                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_PTHREADS=1")
677                endif ()
678                # Prior to version 1.31.3 emcc does not consistently add the cpp standard and remove Emscripten-specific compiler flags
679                # before passing on the work to the underlying LLVM/Clang compiler, this has resulted in preprocessing error when enabling the PCH and ccache
680                # (See https://github.com/kripken/emscripten/issues/3365 for more detail)
681                if (EMSCRIPTEN_EMCC_VERSION VERSION_LESS 1.31.3)
682                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03")
683                endif ()
684                set (CMAKE_C_FLAGS_RELEASE "-Oz -DNDEBUG")
685                set (CMAKE_CXX_FLAGS_RELEASE "-Oz -DNDEBUG")
686                # Remove variables to make the -O3 regalloc easier, embed data in asm.js to reduce number of moving part
687                set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -O3 -s AGGRESSIVE_VARIABLE_ELIMINATION=1 --memory-init-file 0")
688                set (CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -O3 -s AGGRESSIVE_VARIABLE_ELIMINATION=1 --memory-init-file 0")
689                # Preserve LLVM debug information, show line number debug comments, and generate source maps; always disable exception handling codegen
690                set (CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -g4 -s DISABLE_EXCEPTION_CATCHING=1")
691                set (CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} -g4 -s DISABLE_EXCEPTION_CATCHING=1")
692            endif ()
693        elseif (MINGW)
694            # MinGW-specific setup
695            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -static-libgcc -fno-keep-inline-dllexport")
696            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -static-libgcc -static-libstdc++ -fno-keep-inline-dllexport")
697            if (NOT URHO3D_64BIT)
698                set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
699                set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
700                # Prevent auto-vectorize optimization when using -O2, unless stack realign is being enforced globally
701                if (URHO3D_SSE)
702                    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstackrealign")
703                    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mstackrealign")
704                else ()
705                    set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-tree-loop-vectorize -fno-tree-slp-vectorize -fno-tree-vectorize")
706                    set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-tree-loop-vectorize -fno-tree-slp-vectorize -fno-tree-vectorize")
707                endif ()
708            endif ()
709        else ()
710            # Not Android and not Emscripten and not MinGW derivative
711            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")     # This will emit '-DREENTRANT' to compiler and '-lpthread' to linker on Linux and Mac OSX platform
712            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # However, it may emit other equivalent compiler define and/or linker flag on other *nix platforms
713        endif ()
714        set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG -D_DEBUG")
715        set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -D_DEBUG")
716    endif ()
717    if (CMAKE_CXX_COMPILER_ID MATCHES Clang)
718        # Clang-specific
719        set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments")
720        set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments")
721        if (NINJA OR "$ENV{USE_CCACHE}")    # Stringify to guard against undefined environment variable
722            # When ccache support is on, these flags keep the color diagnostics pipe through ccache output and suppress Clang warning due ccache internal preprocessing step
723            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics")
724            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
725        endif ()
726    else ()
727        # GCC-specific
728        if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.1)
729            set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=auto")
730            set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto")
731        endif ()
732    endif ()
733endif ()
734# LuaJIT specific - extra linker flags for linking against LuaJIT (adapted from LuaJIT's original Makefile)
735if (URHO3D_LUAJIT)
736    if (URHO3D_64BIT AND APPLE AND NOT ARM)
737        # 64-bit macOS: it simply won't work without these flags; if you are reading this comment then you may want to know the following also
738        # it's recommended to rebase all (self-compiled) shared libraries which are loaded at runtime on OSX/x64 (e.g. C extension modules for Lua), see: man rebase
739        set (LUAJIT_EXE_LINKER_FLAGS_APPLE "-pagezero_size 10000 -image_base 100000000")
740        set (LUAJIT_SHARED_LINKER_FLAGS_APPLE "-image_base 7fff04c4a000")
741        if (NOT XCODE)
742            set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LUAJIT_EXE_LINKER_FLAGS_APPLE}")
743            set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LUAJIT_SHARED_LINKER_FLAGS_APPLE}")
744        endif ()
745    elseif (URHO3D_LIB_TYPE STREQUAL STATIC AND NOT WIN32 AND NOT APPLE)    # The original condition also checks: AND NOT SunOS AND NOT PS3
746        # We assume user may want to load C modules compiled for plain Lua with require(), so we have to ensure all the public symbols are exported when linking with Urho3D (and therefore LuaJIT) statically
747        # Note: this implies that loading such modules on Windows platform may only work with SHARED library type
748        set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-E")
749    endif ()
750endif ()
751# Trim the leading white space in the compiler/linker flags, if any
752foreach (TYPE C CXX EXE_LINKER SHARED_LINKER)
753    string (REGEX REPLACE "^ +" "" CMAKE_${TYPE}_FLAGS "${CMAKE_${TYPE}_FLAGS}")
754endforeach ()
755
756include (CMakeParseArguments)
757
758# Macro for adjusting target output name by dropping _suffix from the target name
759macro (adjust_target_name)
760    if (TARGET_NAME MATCHES _.*$)
761        string (REGEX REPLACE _.*$ "" OUTPUT_NAME ${TARGET_NAME})
762        set_target_properties (${TARGET_NAME} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
763    endif ()
764endmacro ()
765
766# Macro for checking the SOURCE_FILES variable is properly initialized
767macro (check_source_files)
768    if (NOT SOURCE_FILES)
769        if (NOT ${ARGN} STREQUAL "")
770            message (FATAL_ERROR ${ARGN})
771        else ()
772            message (FATAL_ERROR "Could not configure and generate the project file because no source files have been defined yet. "
773                "You can define the source files explicitly by setting the SOURCE_FILES variable in your CMakeLists.txt; or "
774                "by calling the define_source_files() macro which would by default glob all the C++ source files found in the same scope of "
775                "CMakeLists.txt where the macro is being called and the macro would set the SOURCE_FILES variable automatically. "
776                "If your source files are not located in the same directory as the CMakeLists.txt or your source files are "
777                "more than just C++ language then you probably have to pass in extra arguments when calling the macro in order to make it works. "
778                "See the define_source_files() macro definition in the CMake/Modules/UrhoCommon.cmake for more detail.")
779        endif ()
780    endif ()
781endmacro ()
782
783# Macro for setting symbolic link on platform that supports it
784macro (create_symlink SOURCE DESTINATION)
785    # Make absolute paths so they work more reliably on cmake-gui
786    if (IS_ABSOLUTE ${SOURCE})
787        set (ABS_SOURCE ${SOURCE})
788    else ()
789        set (ABS_SOURCE ${CMAKE_SOURCE_DIR}/${SOURCE})
790    endif ()
791    if (IS_ABSOLUTE ${DESTINATION})
792        set (ABS_DESTINATION ${DESTINATION})
793    else ()
794        set (ABS_DESTINATION ${CMAKE_BINARY_DIR}/${DESTINATION})
795    endif ()
796    if (CMAKE_HOST_WIN32)
797        if (IS_DIRECTORY ${ABS_SOURCE})
798            set (SLASH_D /D)
799        else ()
800            unset (SLASH_D)
801        endif ()
802        if (HAS_MKLINK)
803            if (NOT EXISTS ${ABS_DESTINATION})
804                # Have to use string-REPLACE as file-TO_NATIVE_PATH does not work as expected with MinGW on "backward slash" host system
805                string (REPLACE / \\ BACKWARD_ABS_DESTINATION ${ABS_DESTINATION})
806                string (REPLACE / \\ BACKWARD_ABS_SOURCE ${ABS_SOURCE})
807                execute_process (COMMAND cmd /C mklink ${SLASH_D} ${BACKWARD_ABS_DESTINATION} ${BACKWARD_ABS_SOURCE} OUTPUT_QUIET ERROR_QUIET)
808            endif ()
809        elseif (${ARGN} STREQUAL FALLBACK_TO_COPY)
810            if (SLASH_D)
811                set (COMMAND COMMAND ${CMAKE_COMMAND} -E copy_directory ${ABS_SOURCE} ${ABS_DESTINATION})
812            else ()
813                set (COMMAND COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ABS_SOURCE} ${ABS_DESTINATION})
814            endif ()
815            # Fallback to copy only one time
816            execute_process (${COMMAND})
817            if (TARGET ${TARGET_NAME})
818                # Fallback to copy every time the target is built
819                add_custom_command (TARGET ${TARGET_NAME} POST_BUILD ${COMMAND})
820            endif ()
821        else ()
822            message (WARNING "Unable to create symbolic link on this host system, you may need to manually copy file/dir from \"${SOURCE}\" to \"${DESTINATION}\"")
823        endif ()
824    else ()
825        execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${ABS_SOURCE} ${ABS_DESTINATION})
826    endif ()
827endmacro ()
828
829# Macro for adding additional make clean files
830macro (add_make_clean_files)
831    get_directory_property (ADDITIONAL_MAKE_CLEAN_FILES ADDITIONAL_MAKE_CLEAN_FILES)
832    set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${ADDITIONAL_MAKE_CLEAN_FILES};${ARGN}")
833endmacro ()
834
835# *** THIS IS A DEPRECATED MACRO ***
836# Macro for defining external library dependencies
837# The purpose of this macro is emulate CMake to set the external library dependencies transitively
838# It works for both targets setup within Urho3D project and downstream projects that uses Urho3D as external static/shared library
839# *** THIS IS A DEPRECATED MACRO ***
840macro (define_dependency_libs TARGET)
841    # ThirdParty/SDL external dependency
842    if (${TARGET} MATCHES SDL|Urho3D)
843        if (WIN32)
844            list (APPEND LIBS user32 gdi32 winmm imm32 ole32 oleaut32 version uuid)
845        elseif (APPLE)
846            list (APPEND LIBS iconv)
847        elseif (ANDROID)
848            list (APPEND LIBS dl log android)
849        else ()
850            # Linux
851            if (NOT WEB)
852                list (APPEND LIBS dl m rt)
853            endif ()
854            if (RPI)
855                list (APPEND ABSOLUTE_PATH_LIBS ${VIDEOCORE_LIBRARIES})
856            endif ()
857        endif ()
858    endif ()
859
860    # ThirdParty/kNet & ThirdParty/Civetweb external dependency
861    if (${TARGET} MATCHES Civetweb|kNet|Urho3D)
862        if (WIN32)
863            list (APPEND LIBS ws2_32)
864        endif ()
865    endif ()
866
867    # Urho3D/LuaJIT external dependency
868    if (URHO3D_LUAJIT AND ${TARGET} MATCHES LuaJIT|Urho3D)
869        if (NOT WIN32 AND NOT WEB)
870            list (APPEND LIBS dl m)
871        endif ()
872    endif ()
873
874    # Urho3D external dependency
875    if (${TARGET} STREQUAL Urho3D)
876        # Core
877        if (WIN32)
878            list (APPEND LIBS winmm)
879            if (URHO3D_MINIDUMPS)
880                list (APPEND LIBS dbghelp)
881            endif ()
882        elseif (APPLE)
883            if (ARM)
884                list (APPEND LIBS "-framework AudioToolbox" "-framework AVFoundation" "-framework CoreAudio" "-framework CoreGraphics" "-framework CoreMotion" "-framework Foundation" "-framework GameController" "-framework OpenGLES" "-framework QuartzCore" "-framework UIKit")
885            else ()
886                list (APPEND LIBS "-framework AudioToolbox" "-framework Carbon" "-framework Cocoa" "-framework CoreFoundation" "-framework SystemConfiguration" "-framework CoreAudio" "-framework CoreServices" "-framework CoreVideo" "-framework ForceFeedback" "-framework IOKit" "-framework OpenGL")
887            endif ()
888        endif ()
889
890        # Graphics
891        if (URHO3D_OPENGL)
892            if (APPLE)
893                # Do nothing
894            elseif (WIN32)
895                list (APPEND LIBS opengl32)
896            elseif (ANDROID OR ARM)
897                list (APPEND LIBS GLESv1_CM GLESv2)
898            else ()
899                list (APPEND LIBS GL)
900            endif ()
901        elseif (DIRECT3D_LIBRARIES)
902            list (APPEND LIBS ${DIRECT3D_LIBRARIES})
903        endif ()
904
905        # Database
906        if (URHO3D_DATABASE_ODBC)
907            list (APPEND LIBS ${ODBC_LIBRARIES})
908        endif ()
909
910        # This variable value can either be 'Urho3D' target or an absolute path to an actual static/shared Urho3D library or empty (if we are building the library itself)
911        # The former would cause CMake not only to link against the Urho3D library but also to add a dependency to Urho3D target
912        if (URHO3D_LIBRARIES)
913            if (WIN32 AND URHO3D_LIBRARIES_DBG AND URHO3D_LIBRARIES_REL AND TARGET ${TARGET_NAME})
914                # Special handling when both debug and release libraries are found
915                target_link_libraries (${TARGET_NAME} debug ${URHO3D_LIBRARIES_DBG} optimized ${URHO3D_LIBRARIES_REL})
916            else ()
917                if (TARGET ${TARGET}_universal)
918                    add_dependencies (${TARGET_NAME} ${TARGET}_universal)
919                endif ()
920                if (URHO3D_LIB_TYPE STREQUAL MODULE)
921                    if (TARGET ${TARGET})
922                        add_dependencies (${TARGET_NAME} ${TARGET})
923                    endif ()
924                else ()
925                    list (APPEND ABSOLUTE_PATH_LIBS ${URHO3D_LIBRARIES})
926                endif ()
927            endif ()
928        endif ()
929    endif ()
930endmacro ()
931
932# Macro for defining source files with optional arguments as follows:
933#  GLOB_CPP_PATTERNS <list> - Use the provided globbing patterns for CPP_FILES instead of the default *.cpp
934#  GLOB_H_PATTERNS <list> - Use the provided globbing patterns for H_FILES instead of the default *.h
935#  EXCLUDE_PATTERNS <list> - Use the provided regex patterns for excluding the unwanted matched source files
936#  EXTRA_CPP_FILES <list> - Include the provided list of files into CPP_FILES result
937#  EXTRA_H_FILES <list> - Include the provided list of files into H_FILES result
938#  PCH <list> - Enable precompiled header support on the defined source files using the specified header file, the list is "<path/to/header> [C++|C]"
939#  RECURSE - Option to glob recursively
940#  GROUP - Option to group source files based on its relative path to the corresponding parent directory
941macro (define_source_files)
942    # Source files are defined by globbing source files in current source directory and also by including the extra source files if provided
943    cmake_parse_arguments (ARG "RECURSE;GROUP" "" "PCH;EXTRA_CPP_FILES;EXTRA_H_FILES;GLOB_CPP_PATTERNS;GLOB_H_PATTERNS;EXCLUDE_PATTERNS" ${ARGN})
944    if (NOT ARG_GLOB_CPP_PATTERNS)
945        set (ARG_GLOB_CPP_PATTERNS *.cpp)    # Default glob pattern
946    endif ()
947    if (NOT ARG_GLOB_H_PATTERNS)
948        set (ARG_GLOB_H_PATTERNS *.h)
949    endif ()
950    if (ARG_RECURSE)
951        set (ARG_RECURSE _RECURSE)
952    else ()
953        unset (ARG_RECURSE)
954    endif ()
955    file (GLOB${ARG_RECURSE} CPP_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARG_GLOB_CPP_PATTERNS})
956    file (GLOB${ARG_RECURSE} H_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARG_GLOB_H_PATTERNS})
957    if (ARG_EXCLUDE_PATTERNS)
958        set (CPP_FILES_WITH_SENTINEL ";${CPP_FILES};")  # Stringify the lists
959        set (H_FILES_WITH_SENTINEL ";${H_FILES};")
960        foreach (PATTERN ${ARG_EXCLUDE_PATTERNS})
961            foreach (LOOP RANGE 1)
962                string (REGEX REPLACE ";${PATTERN};" ";;" CPP_FILES_WITH_SENTINEL "${CPP_FILES_WITH_SENTINEL}")
963                string (REGEX REPLACE ";${PATTERN};" ";;" H_FILES_WITH_SENTINEL "${H_FILES_WITH_SENTINEL}")
964            endforeach ()
965        endforeach ()
966        set (CPP_FILES ${CPP_FILES_WITH_SENTINEL})      # Convert strings back to lists, extra sentinels are harmless
967        set (H_FILES ${H_FILES_WITH_SENTINEL})
968    endif ()
969    list (APPEND CPP_FILES ${ARG_EXTRA_CPP_FILES})
970    list (APPEND H_FILES ${ARG_EXTRA_H_FILES})
971    set (SOURCE_FILES ${CPP_FILES} ${H_FILES})
972    # Optionally enable PCH
973    if (ARG_PCH)
974        enable_pch (${ARG_PCH})
975    endif ()
976    # Optionally group the sources based on their physical subdirectories
977    if (ARG_GROUP)
978        foreach (CPP_FILE ${CPP_FILES})
979            get_filename_component (PATH ${CPP_FILE} PATH)
980            if (PATH)
981                string (REPLACE / \\ PATH ${PATH})
982                source_group ("Source Files\\${PATH}" FILES ${CPP_FILE})
983            endif ()
984        endforeach ()
985        foreach (H_FILE ${H_FILES})
986            get_filename_component (PATH ${H_FILE} PATH)
987            if (PATH)
988                string (REPLACE / \\ PATH ${PATH})
989                source_group ("Header Files\\${PATH}" FILES ${H_FILE})
990            endif ()
991        endforeach ()
992    endif ()
993endmacro ()
994
995# Macro for defining resource directories with optional arguments as follows:
996#  GLOB_PATTERNS <list> - Use the provided globbing patterns for resource directories, default to "${CMAKE_SOURCE_DIR}/bin/*Data"
997#  EXCLUDE_PATTERNS <list> - Use the provided regex patterns for excluding the unwanted matched directories
998#  EXTRA_DIRS <list> - Include the provided list of directories into globbing result
999#  HTML_SHELL <value> - An absolute path to the HTML shell file (only applicable for Web platform)
1000macro (define_resource_dirs)
1001    check_source_files ("Could not call define_resource_dirs() macro before define_source_files() macro.")
1002    cmake_parse_arguments (ARG "" "HTML_SHELL" "GLOB_PATTERNS;EXCLUDE_PATTERNS;EXTRA_DIRS" ${ARGN})
1003    if (WEB AND ARG_HTML_SHELL)
1004        add_html_shell (${ARG_HTML_SHELL})
1005    endif ()
1006    # If not explicitly specified then use the Urho3D project structure convention
1007    if (NOT ARG_GLOB_PATTERNS)
1008        set (ARG_GLOB_PATTERNS ${CMAKE_SOURCE_DIR}/bin/*Data)
1009    endif ()
1010    file (GLOB GLOB_RESULTS ${ARG_GLOB_PATTERNS})
1011    unset (GLOB_DIRS)
1012    foreach (DIR ${GLOB_RESULTS})
1013        if (IS_DIRECTORY ${DIR})
1014            list (APPEND GLOB_DIRS ${DIR})
1015        endif ()
1016    endforeach ()
1017    if (ARG_EXCLUDE_PATTERNS)
1018        set (GLOB_DIRS_WITH_SENTINEL ";${GLOB_DIRS};")  # Stringify the lists
1019        foreach (PATTERN ${ARG_EXCLUDE_PATTERNS})
1020            foreach (LOOP RANGE 1)
1021                string (REGEX REPLACE ";${PATTERN};" ";;" GLOB_DIRS_WITH_SENTINEL "${GLOB_DIRS_WITH_SENTINEL}")
1022            endforeach ()
1023        endforeach ()
1024        set (GLOB_DIRS ${GLOB_DIRS_WITH_SENTINEL})      # Convert strings back to lists, extra sentinels are harmless
1025    endif ()
1026    list (APPEND RESOURCE_DIRS ${GLOB_DIRS} ${ARG_EXTRA_DIRS})
1027    source_group ("Resource Dirs" FILES ${RESOURCE_DIRS})
1028    # Populate all the variables required by resource packaging, if the build option is enabled
1029    if (URHO3D_PACKAGING AND RESOURCE_DIRS)
1030        foreach (DIR ${RESOURCE_DIRS})
1031            get_filename_component (NAME ${DIR} NAME)
1032            if (ANDROID)
1033                set (RESOURCE_${DIR}_PATHNAME ${CMAKE_BINARY_DIR}/assets/${NAME}.pak)
1034            else ()
1035                set (RESOURCE_${DIR}_PATHNAME ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${NAME}.pak)
1036            endif ()
1037            list (APPEND RESOURCE_PAKS ${RESOURCE_${DIR}_PATHNAME})
1038            if (EMSCRIPTEN AND NOT EMSCRIPTEN_SHARE_DATA)
1039                # Set the custom EMCC_OPTION property to preload the *.pak individually
1040                set_source_files_properties (${RESOURCE_${DIR}_PATHNAME} PROPERTIES EMCC_OPTION preload-file EMCC_FILE_ALIAS "${NAME}.pak")
1041            endif ()
1042        endforeach ()
1043        set_property (SOURCE ${RESOURCE_PAKS} PROPERTY GENERATED TRUE)
1044        if (WEB)
1045            if (EMSCRIPTEN)
1046                # Set the custom EMCC_OPTION property to peload the generated shared data file
1047                if (EMSCRIPTEN_SHARE_DATA)
1048                    set (SHARED_RESOURCE_JS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_PROJECT_NAME}.js)
1049                    list (APPEND SOURCE_FILES ${SHARED_RESOURCE_JS} ${SHARED_RESOURCE_JS}.data)
1050                    # DEST_BUNDLE_DIR may be empty when macro caller does not wish to install anything
1051                    if (DEST_BUNDLE_DIR)
1052                        install (FILES ${SHARED_RESOURCE_JS} ${SHARED_RESOURCE_JS}.data DESTINATION ${DEST_BUNDLE_DIR})
1053                    endif ()
1054                    # Define a custom command for generating a shared data file
1055                    if (RESOURCE_PAKS)
1056                        # When sharing a single data file, all main targets are assumed to use a same set of resource paks
1057                        foreach (FILE ${RESOURCE_PAKS})
1058                            get_filename_component (NAME ${FILE} NAME)
1059                            list (APPEND PAK_NAMES ${NAME})
1060                        endforeach ()
1061                        if (CMAKE_BUILD_TYPE STREQUAL Debug AND EMSCRIPTEN_EMCC_VERSION VERSION_GREATER 1.32.2)
1062                            set (SEPARATE_METADATA --separate-metadata)
1063                        endif ()
1064                        add_custom_command (OUTPUT ${SHARED_RESOURCE_JS} ${SHARED_RESOURCE_JS}.data
1065                            COMMAND ${EMPACKAGER} ${SHARED_RESOURCE_JS}.data --preload ${PAK_NAMES} --js-output=${SHARED_RESOURCE_JS} --use-preload-cache ${SEPARATE_METADATA}
1066                            DEPENDS RESOURCE_CHECK ${RESOURCE_PAKS}
1067                            WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
1068                            COMMENT "Generating shared data file")
1069                    endif ()
1070                endif ()
1071            endif ()
1072        endif ()
1073    endif ()
1074    if (XCODE)
1075        if (NOT RESOURCE_FILES)
1076            # Default app bundle icon
1077            set (RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.icns)
1078            if (ARM)
1079                # Default app icon on the iOS/tvOS home screen
1080                list (APPEND RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.png)
1081            endif ()
1082        endif ()
1083        # Group them together under 'Resources' in Xcode IDE
1084        source_group (Resources FILES ${RESOURCE_PAKS} ${RESOURCE_FILES})     # RESOURCE_PAKS could be empty if packaging is not requested
1085        # But only use either paks or dirs
1086        if (RESOURCE_PAKS)
1087            set_source_files_properties (${RESOURCE_PAKS} ${RESOURCE_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
1088        else ()
1089            set_source_files_properties (${RESOURCE_DIRS} ${RESOURCE_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
1090        endif ()
1091    endif ()
1092    list (APPEND SOURCE_FILES ${RESOURCE_DIRS} ${RESOURCE_PAKS} ${RESOURCE_FILES})
1093endmacro()
1094
1095# Macro fo adding a HTML shell-file when targeting Web platform
1096macro (add_html_shell)
1097    check_source_files ("Could not call add_html_shell() macro before define_source_files() macro.")
1098    if (EMSCRIPTEN)
1099        if (NOT ${ARGN} STREQUAL "")
1100            set (HTML_SHELL ${ARGN})
1101        else ()
1102            # Create Urho3D custom HTML shell that also embeds our own project logo
1103            if (NOT EXISTS ${CMAKE_BINARY_DIR}/Source/shell.html)
1104                file (READ ${EMSCRIPTEN_ROOT_PATH}/src/shell.html HTML_SHELL)
1105                string (REPLACE "<!doctype html>" "#!/usr/bin/env ${EMSCRIPTEN_EMRUN_BROWSER}\n<!-- This is a generated file. DO NOT EDIT!-->\n\n<!doctype html>" HTML_SHELL "${HTML_SHELL}")     # Stringify to preserve semicolons
1106                string (REPLACE "<body>" "<body>\n<script>document.body.innerHTML=document.body.innerHTML.replace(/^#!.*\\n/, '');</script>\n<a href=\"https://urho3d.github.io\" title=\"Urho3D Homepage\"><img src=\"https://urho3d.github.io/assets/images/logo.png\" alt=\"link to https://urho3d.github.io\" height=\"80\" width=\"160\" /></a>\n" HTML_SHELL "${HTML_SHELL}")
1107                file (WRITE ${CMAKE_BINARY_DIR}/Source/shell.html "${HTML_SHELL}")
1108            endif ()
1109            set (HTML_SHELL ${CMAKE_BINARY_DIR}/Source/shell.html)
1110        endif ()
1111        list (APPEND SOURCE_FILES ${HTML_SHELL})
1112        set_source_files_properties (${HTML_SHELL} PROPERTIES EMCC_OPTION shell-file)
1113    endif ()
1114endmacro ()
1115
1116include (GenerateExportHeader)
1117
1118# Macro for precompiling header (On MSVC, the dummy C++ or C implementation file for precompiling the header file would be generated if not already exists)
1119# This macro should be called before the CMake target has been added
1120# Typically, user should indirectly call this macro by using the 'PCH' option when calling define_source_files() macro
1121macro (enable_pch HEADER_PATHNAME)
1122    # No op when PCH support is not enabled
1123    if (URHO3D_PCH)
1124        # Get the optional LANG parameter to indicate whether the header should be treated as C or C++ header, default to C++
1125        if ("${ARGN}" STREQUAL C)   # Stringify as the LANG paramater could be empty
1126            set (EXT c)
1127            set (LANG C)
1128            set (LANG_H c-header)
1129        else ()
1130            # This is the default
1131            set (EXT cpp)
1132            set (LANG CXX)
1133            set (LANG_H c++-header)
1134        endif ()
1135        # Relative path is resolved using CMAKE_CURRENT_SOURCE_DIR
1136        if (IS_ABSOLUTE ${HEADER_PATHNAME})
1137            set (ABS_HEADER_PATHNAME ${HEADER_PATHNAME})
1138        else ()
1139            set (ABS_HEADER_PATHNAME ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_PATHNAME})
1140        endif ()
1141        # Determine the precompiled header output filename
1142        get_filename_component (HEADER_FILENAME ${HEADER_PATHNAME} NAME)
1143        if (CMAKE_COMPILER_IS_GNUCXX)
1144            # GNU g++
1145            set (PCH_FILENAME ${HEADER_FILENAME}.gch)
1146        else ()
1147            # Clang or MSVC
1148            set (PCH_FILENAME ${HEADER_FILENAME}.pch)
1149        endif ()
1150
1151        if (MSVC)
1152            get_filename_component (NAME_WE ${HEADER_FILENAME} NAME_WE)
1153            if (TARGET ${TARGET_NAME})
1154                if (VS)
1155                    # VS is multi-config, the exact path is only known during actual build time based on effective build config
1156                    set (PCH_PATHNAME "$(IntDir)${PCH_FILENAME}")
1157                else ()
1158                    set (PCH_PATHNAME ${CMAKE_CURRENT_BINARY_DIR}/${PCH_FILENAME})
1159                endif ()
1160                foreach (FILE ${SOURCE_FILES})
1161                    if (FILE MATCHES \\.${EXT}$)
1162                        if (FILE MATCHES ${NAME_WE}\\.${EXT}$)
1163                            # Precompiling header file
1164                            set_property (SOURCE ${FILE} APPEND_STRING PROPERTY COMPILE_FLAGS " /Fp${PCH_PATHNAME} /Yc${HEADER_FILENAME}")     # Need a leading space for appending
1165                        else ()
1166                            # Using precompiled header file
1167                            set_property (SOURCE ${FILE} APPEND_STRING PROPERTY COMPILE_FLAGS " /Fp${PCH_PATHNAME} /Yu${HEADER_FILENAME} /FI${HEADER_FILENAME}")
1168                        endif ()
1169                    endif ()
1170                endforeach ()
1171                unset (${TARGET_NAME}_HEADER_PATHNAME)
1172            else ()
1173                # The target has not been created yet, so set an internal variable to come back here again later
1174                set (${TARGET_NAME}_HEADER_PATHNAME ${ARGV})
1175                # But proceed to add the dummy C++ or C implementation file if necessary
1176                set (${LANG}_FILENAME ${NAME_WE}.${EXT})
1177                get_filename_component (PATH ${HEADER_PATHNAME} PATH)
1178                if (PATH)
1179                    set (PATH ${PATH}/)
1180                endif ()
1181                list (FIND SOURCE_FILES ${PATH}${${LANG}_FILENAME} ${LANG}_FILENAME_FOUND)
1182                if (${LANG}_FILENAME_FOUND STREQUAL -1)
1183                    if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${${LANG}_FILENAME})
1184                        # Only generate it once so that its timestamp is not touched unnecessarily
1185                        file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/${${LANG}_FILENAME} "// This is a generated file. DO NOT EDIT!\n\n#include \"${HEADER_FILENAME}\"")
1186                    endif ()
1187                    list (INSERT SOURCE_FILES 0 ${${LANG}_FILENAME})
1188                endif ()
1189            endif ()
1190        elseif (XCODE)
1191            if (TARGET ${TARGET_NAME})
1192                # Precompiling and using precompiled header file
1193                set_target_properties (${TARGET_NAME} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER YES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER ${ABS_HEADER_PATHNAME})
1194                unset (${TARGET_NAME}_HEADER_PATHNAME)
1195            else ()
1196                # The target has not been created yet, so set an internal variable to come back here again later
1197                set (${TARGET_NAME}_HEADER_PATHNAME ${ARGV})
1198            endif ()
1199        else ()
1200            # GCC or Clang
1201            if (TARGET ${TARGET_NAME})
1202                # Precompiling header file
1203                get_directory_property (COMPILE_DEFINITIONS COMPILE_DEFINITIONS)
1204                get_directory_property (INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES)
1205                get_target_property (TYPE ${TARGET_NAME} TYPE)
1206                if (TYPE MATCHES SHARED|MODULE)
1207                    list (APPEND COMPILE_DEFINITIONS ${TARGET_NAME}_EXPORTS)
1208                    if (LANG STREQUAL CXX)
1209                        _test_compiler_hidden_visibility ()
1210                    endif ()
1211                endif ()
1212                # Use PIC flags as necessary, except when compiling using MinGW which already uses PIC flags for all codes
1213                if (NOT MINGW)
1214                    get_target_property (PIC ${TARGET_NAME} POSITION_INDEPENDENT_CODE)
1215                    if (PIC)
1216                        set (PIC_FLAGS -fPIC)
1217                    endif ()
1218                endif ()
1219                string (REPLACE ";" " -D" COMPILE_DEFINITIONS "-D${COMPILE_DEFINITIONS}")
1220                string (REPLACE "\"" "\\\"" COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS})
1221                string (REPLACE ";" "\" -I\"" INCLUDE_DIRECTORIES "-I\"${INCLUDE_DIRECTORIES}\"")
1222                if (CMAKE_SYSROOT)
1223                    set (SYSROOT_FLAGS "--sysroot=\"${CMAKE_SYSROOT}\"")
1224                endif ()
1225                # Make sure the precompiled headers are not stale by creating custom rules to re-compile the header as necessary
1226                file (MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PCH_FILENAME})
1227                set (ABS_PATH_PCH ${CMAKE_CURRENT_BINARY_DIR}/${HEADER_FILENAME})
1228                foreach (CONFIG ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})   # These two vars are mutually exclusive
1229                    # Generate *.rsp containing configuration specific compiler flags
1230                    string (TOUPPER ${CONFIG} UPPERCASE_CONFIG)
1231                    file (WRITE ${ABS_PATH_PCH}.${CONFIG}.pch.rsp.new "${COMPILE_DEFINITIONS} ${SYSROOT_FLAGS} ${CLANG_${LANG}_FLAGS} ${CMAKE_${LANG}_FLAGS} ${CMAKE_${LANG}_FLAGS_${UPPERCASE_CONFIG}} ${COMPILER_HIDDEN_VISIBILITY_FLAGS} ${COMPILER_HIDDEN_INLINE_VISIBILITY_FLAGS} ${PIC_FLAGS} ${INCLUDE_DIRECTORIES} -c -x ${LANG_H}")
1232                    execute_process (COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ABS_PATH_PCH}.${CONFIG}.pch.rsp.new ${ABS_PATH_PCH}.${CONFIG}.pch.rsp)
1233                    file (REMOVE ${ABS_PATH_PCH}.${CONFIG}.pch.rsp.new)
1234                    if (NOT ${TARGET_NAME}_PCH_DEPS)
1235                        if (NOT CMAKE_CURRENT_SOURCE_DIR EQUAL CMAKE_CURRENT_BINARY_DIR)
1236                            # Create a dummy initial PCH file in the Out-of-source build tree to keep CLion happy
1237                            execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${ABS_PATH_PCH})
1238                        endif ()
1239                        # Determine the dependency list
1240                        execute_process (COMMAND ${CMAKE_${LANG}_COMPILER} @${ABS_PATH_PCH}.${CONFIG}.pch.rsp -MTdeps -MM -MF ${ABS_PATH_PCH}.d ${ABS_HEADER_PATHNAME} RESULT_VARIABLE ${LANG}_COMPILER_EXIT_CODE)
1241                        if (NOT ${LANG}_COMPILER_EXIT_CODE EQUAL 0)
1242                            message (FATAL_ERROR "Could not generate dependency list for PCH. There is something wrong with your compiler toolchain. "
1243                                "Ensure its bin path is in the PATH environment variable or ensure CMake can find CC/CXX in your build environment.")
1244                        endif ()
1245                        file (STRINGS ${ABS_PATH_PCH}.d ${TARGET_NAME}_PCH_DEPS)
1246                        string (REGEX REPLACE "^deps: *| *\\; *" ";" ${TARGET_NAME}_PCH_DEPS ${${TARGET_NAME}_PCH_DEPS})
1247                        string (REGEX REPLACE "\\\\ " "\ " ${TARGET_NAME}_PCH_DEPS "${${TARGET_NAME}_PCH_DEPS}")    # Need to stringify the second time to preserve the semicolons
1248                    endif ()
1249                    # Create the rule that depends on the included headers
1250                    add_custom_command (OUTPUT ${HEADER_FILENAME}.${CONFIG}.pch.trigger
1251                        COMMAND ${CMAKE_${LANG}_COMPILER} @${ABS_PATH_PCH}.${CONFIG}.pch.rsp -o ${PCH_FILENAME}/${PCH_FILENAME}.${CONFIG} ${ABS_HEADER_PATHNAME}
1252                        COMMAND ${CMAKE_COMMAND} -E touch ${HEADER_FILENAME}.${CONFIG}.pch.trigger
1253                        DEPENDS ${ABS_PATH_PCH}.${CONFIG}.pch.rsp ${${TARGET_NAME}_PCH_DEPS}
1254                        COMMENT "Precompiling header file '${HEADER_FILENAME}' for ${CONFIG} configuration")
1255                    add_make_clean_files (${PCH_FILENAME}/${PCH_FILENAME}.${CONFIG})
1256                endforeach ()
1257                # Using precompiled header file
1258                set (CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS} -include \"${ABS_PATH_PCH}\"")
1259                unset (${TARGET_NAME}_HEADER_PATHNAME)
1260            else ()
1261                # The target has not been created yet, so set an internal variable to come back here again later
1262                set (${TARGET_NAME}_HEADER_PATHNAME ${ARGV})
1263                # But proceed to add the dummy source file(s) to trigger the custom command output rule
1264                if (CMAKE_CONFIGURATION_TYPES)
1265                    # Multi-config, trigger all rules and let the compiler to choose which precompiled header is suitable to use
1266                    foreach (CONFIG ${CMAKE_CONFIGURATION_TYPES})
1267                        list (APPEND TRIGGERS ${HEADER_FILENAME}.${CONFIG}.pch.trigger)
1268                    endforeach ()
1269                else ()
1270                    # Single-config, just trigger the corresponding rule matching the current build configuration
1271                    set (TRIGGERS ${HEADER_FILENAME}.${CMAKE_BUILD_TYPE}.pch.trigger)
1272                endif ()
1273                list (APPEND SOURCE_FILES ${TRIGGERS})
1274            endif ()
1275        endif ()
1276    endif ()
1277endmacro ()
1278
1279# Macro for finding file in Urho3D build tree or Urho3D SDK
1280macro (find_Urho3D_file VAR NAME)
1281    # Pass the arguments to the actual find command
1282    cmake_parse_arguments (ARG "" "DOC;MSG_MODE" "HINTS;PATHS;PATH_SUFFIXES" ${ARGN})
1283    find_file (${VAR} ${NAME} HINTS ${ARG_HINTS} PATHS ${ARG_PATHS} PATH_SUFFIXES ${ARG_PATH_SUFFIXES} DOC ${ARG_DOC} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
1284    mark_as_advanced (${VAR})  # Hide it from cmake-gui in non-advanced mode
1285    if (NOT ${VAR} AND ARG_MSG_MODE)
1286        message (${ARG_MSG_MODE}
1287            "Could not find ${VAR} file in the Urho3D build tree or Urho3D SDK. "
1288            "Please reconfigure and rebuild your Urho3D build tree or reinstall the SDK for the correct target platform.")
1289    endif ()
1290endmacro ()
1291
1292# Macro for finding tool in Urho3D build tree or Urho3D SDK
1293macro (find_Urho3D_tool VAR NAME)
1294    # Pass the arguments to the actual find command
1295    cmake_parse_arguments (ARG "" "DOC;MSG_MODE" "HINTS;PATHS;PATH_SUFFIXES" ${ARGN})
1296    find_program (${VAR} ${NAME} HINTS ${ARG_HINTS} PATHS ${ARG_PATHS} PATH_SUFFIXES ${ARG_PATH_SUFFIXES} DOC ${ARG_DOC} NO_DEFAULT_PATH)
1297    mark_as_advanced (${VAR})  # Hide it from cmake-gui in non-advanced mode
1298    if (NOT ${VAR})
1299        set (${VAR} ${CMAKE_BINARY_DIR}/bin/tool/${NAME})
1300        if (ARG_MSG_MODE AND NOT CMAKE_PROJECT_NAME STREQUAL Urho3D)
1301            message (${ARG_MSG_MODE}
1302                "Could not find ${VAR} tool in the Urho3D build tree or Urho3D SDK. Your project may not build successfully without this tool. "
1303                "You may have to first rebuild the Urho3D in its build tree or reinstall Urho3D SDK to get this tool built or installed properly. "
1304                "Alternatively, copy the ${VAR} executable manually into bin/tool subdirectory in your own project build tree.")
1305        endif ()
1306    endif ()
1307endmacro ()
1308
1309# Macro for setting up header files installation for the SDK and the build tree (only support subset of install command arguments)
1310#  FILES <list> - File list to be installed
1311#  DIRECTORY <list> - Directory list to be installed
1312#  FILES_MATCHING - Option to perform file pattern matching on DIRECTORY list
1313#  USE_FILE_SYMLINK - Option to use file symlinks on the matched files found in the DIRECTORY list
1314#  BUILD_TREE_ONLY - Option to install the header files into the build tree only
1315#  PATTERN <list> - Pattern list to be used in file pattern matching option
1316#  BASE <value> - An absolute base path to be prepended to the destination path when installing to build tree, default to build tree
1317#  DESTINATION <value> - A relative destination path to be installed to
1318#  ACCUMULATE <value> - Accumulate the header files into the specified CMake variable, implies USE_FILE_SYMLINK when input list is a directory
1319macro (install_header_files)
1320    # Need to check if the destination variable is defined first because this macro could be called by downstream project that does not wish to install anything
1321    if (DEST_INCLUDE_DIR)
1322        # Parse the arguments for the underlying install command for the SDK
1323        cmake_parse_arguments (ARG "FILES_MATCHING;USE_FILE_SYMLINK;BUILD_TREE_ONLY" "BASE;DESTINATION;ACCUMULATE" "FILES;DIRECTORY;PATTERN" ${ARGN})
1324        unset (INSTALL_MATCHING)
1325        if (ARG_FILES)
1326            set (INSTALL_TYPE FILES)
1327            set (INSTALL_SOURCES ${ARG_FILES})
1328        elseif (ARG_DIRECTORY)
1329            set (INSTALL_TYPE DIRECTORY)
1330            set (INSTALL_SOURCES ${ARG_DIRECTORY})
1331            if (ARG_FILES_MATCHING)
1332                set (INSTALL_MATCHING FILES_MATCHING)
1333                # Our macro supports PATTERN <list> but CMake's install command does not, so convert the list to: PATTERN <value1> PATTERN <value2> ...
1334                foreach (PATTERN ${ARG_PATTERN})
1335                    list (APPEND INSTALL_MATCHING PATTERN ${PATTERN})
1336                endforeach ()
1337            endif ()
1338        else ()
1339            message (FATAL_ERROR "Couldn't setup install command because the install type is not specified.")
1340        endif ()
1341        if (NOT ARG_DESTINATION)
1342            message (FATAL_ERROR "Couldn't setup install command because the install destination is not specified.")
1343        endif ()
1344        if (NOT ARG_BUILD_TREE_ONLY AND NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
1345            install (${INSTALL_TYPE} ${INSTALL_SOURCES} DESTINATION ${ARG_DESTINATION} ${INSTALL_MATCHING})
1346        endif ()
1347
1348        # Reparse the arguments for the create_symlink macro to "install" the header files in the build tree
1349        if (NOT ARG_BASE)
1350            set (ARG_BASE ${CMAKE_BINARY_DIR})  # Use build tree as base path
1351        endif ()
1352        foreach (INSTALL_SOURCE ${INSTALL_SOURCES})
1353            if (NOT IS_ABSOLUTE ${INSTALL_SOURCE})
1354                set (INSTALL_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${INSTALL_SOURCE})
1355            endif ()
1356            if (INSTALL_SOURCE MATCHES /$)
1357                # Source is a directory
1358                if (ARG_USE_FILE_SYMLINK OR ARG_ACCUMULATE OR BASH_ON_WINDOWS)
1359                    # Use file symlink for each individual files in the source directory
1360                    if (IS_SYMLINK ${ARG_DESTINATION} AND NOT CMAKE_HOST_WIN32)
1361                        execute_process (COMMAND ${CMAKE_COMMAND} -E remove ${ARG_DESTINATION})
1362                    endif ()
1363                    set (GLOBBING_EXPRESSION RELATIVE ${INSTALL_SOURCE})
1364                    if (ARG_FILES_MATCHING)
1365                        foreach (PATTERN ${ARG_PATTERN})
1366                            list (APPEND GLOBBING_EXPRESSION ${INSTALL_SOURCE}${PATTERN})
1367                        endforeach ()
1368                    else ()
1369                        list (APPEND GLOBBING_EXPRESSION ${INSTALL_SOURCE}*)
1370                    endif ()
1371                    file (GLOB_RECURSE NAMES ${GLOBBING_EXPRESSION})
1372                    foreach (NAME ${NAMES})
1373                        get_filename_component (PATH ${ARG_DESTINATION}/${NAME} PATH)
1374                        # Recreate the source directory structure in the destination path
1375                        if (NOT EXISTS ${ARG_BASE}/${PATH})
1376                            file (MAKE_DIRECTORY ${ARG_BASE}/${PATH})
1377                        endif ()
1378                        create_symlink (${INSTALL_SOURCE}${NAME} ${ARG_DESTINATION}/${NAME} FALLBACK_TO_COPY)
1379                        if (ARG_ACCUMULATE)
1380                            list (APPEND ${ARG_ACCUMULATE} ${ARG_DESTINATION}/${NAME})
1381                        endif ()
1382                    endforeach ()
1383                else ()
1384                    # Use a single symlink pointing to the source directory
1385                    if (NOT IS_SYMLINK ${ARG_DESTINATION} AND NOT CMAKE_HOST_WIN32)
1386                        execute_process (COMMAND ${CMAKE_COMMAND} -E remove_directory ${ARG_DESTINATION})
1387                    endif ()
1388                    create_symlink (${INSTALL_SOURCE} ${ARG_DESTINATION} FALLBACK_TO_COPY)
1389                endif ()
1390            else ()
1391                # Source is a file (it could also be actually a directory to be treated as a "file", i.e. for creating symlink pointing to the directory)
1392                get_filename_component (NAME ${INSTALL_SOURCE} NAME)
1393                create_symlink (${INSTALL_SOURCE} ${ARG_DESTINATION}/${NAME} FALLBACK_TO_COPY)
1394                if (ARG_ACCUMULATE)
1395                    list (APPEND ${ARG_ACCUMULATE} ${ARG_DESTINATION}/${NAME})
1396                endif ()
1397            endif ()
1398        endforeach ()
1399    endif ()
1400endmacro ()
1401
1402# Macro for setting common output directories
1403macro (set_output_directories OUTPUT_PATH)
1404    cmake_parse_arguments (ARG LOCAL "" "" ${ARGN})
1405    if (ARG_LOCAL)
1406        unset (SCOPE)
1407        unset (OUTPUT_DIRECTORY_PROPERTIES)
1408    else ()
1409        set (SCOPE CMAKE_)
1410    endif ()
1411    foreach (TYPE ${ARG_UNPARSED_ARGUMENTS})
1412        set (${SCOPE}${TYPE}_OUTPUT_DIRECTORY ${OUTPUT_PATH})
1413        list (APPEND OUTPUT_DIRECTORY_PROPERTIES ${TYPE}_OUTPUT_DIRECTORY ${${TYPE}_OUTPUT_DIRECTORY})
1414        foreach (CONFIG ${CMAKE_CONFIGURATION_TYPES})
1415            string (TOUPPER ${CONFIG} CONFIG)
1416            set (${SCOPE}${TYPE}_OUTPUT_DIRECTORY_${CONFIG} ${OUTPUT_PATH})
1417            list (APPEND OUTPUT_DIRECTORY_PROPERTIES ${TYPE}_OUTPUT_DIRECTORY_${CONFIG} ${${TYPE}_OUTPUT_DIRECTORY_${CONFIG}})
1418        endforeach ()
1419        if (TYPE STREQUAL RUNTIME AND NOT ${OUTPUT_PATH} STREQUAL .)
1420            file (RELATIVE_PATH REL_OUTPUT_PATH ${CMAKE_BINARY_DIR} ${OUTPUT_PATH})
1421            set (DEST_RUNTIME_DIR ${REL_OUTPUT_PATH})
1422        endif ()
1423    endforeach ()
1424    if (ARG_LOCAL)
1425        list (APPEND TARGET_PROPERTIES ${OUTPUT_DIRECTORY_PROPERTIES})
1426    endif ()
1427endmacro ()
1428
1429# Macro for setting up an executable target
1430# Macro arguments:
1431#  PRIVATE - setup executable target without installing it
1432#  TOOL - setup a tool executable target
1433#  NODEPS - setup executable target without defining Urho3D dependency libraries
1434#  WIN32/MACOSX_BUNDLE/EXCLUDE_FROM_ALL - see CMake help on add_executable() command
1435# CMake variables:
1436#  SOURCE_FILES - list of source files
1437#  INCLUDE_DIRS - list of directories for include search path
1438#  LIBS - list of dependent libraries that are built internally in the project
1439#  ABSOLUTE_PATH_LIBS - list of dependent libraries that are external to the project
1440#  LINK_DEPENDS - list of additional files on which a target binary depends for linking (Makefile-based generator only)
1441#  LINK_FLAGS - list of additional link flags
1442#  TARGET_PROPERTIES - list of target properties
1443macro (setup_executable)
1444    cmake_parse_arguments (ARG "PRIVATE;TOOL;NODEPS" "" "" ${ARGN})
1445    check_source_files ()
1446    add_executable (${TARGET_NAME} ${ARG_UNPARSED_ARGUMENTS} ${SOURCE_FILES})
1447    set (RUNTIME_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
1448    if (ARG_PRIVATE)
1449        set_output_directories (. LOCAL RUNTIME PDB)
1450        set (RUNTIME_DIR .)
1451    endif ()
1452    if (ARG_TOOL)
1453        list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES)
1454        if (NOT ARG_PRIVATE AND NOT DEST_RUNTIME_DIR MATCHES tool)
1455            set_output_directories (${CMAKE_BINARY_DIR}/bin/tool LOCAL RUNTIME PDB)
1456            set (RUNTIME_DIR ${CMAKE_BINARY_DIR}/bin/tool)
1457        endif ()
1458    endif ()
1459    if (NOT ARG_NODEPS)
1460        define_dependency_libs (Urho3D)
1461    endif ()
1462    if (XCODE AND LUAJIT_EXE_LINKER_FLAGS_APPLE)
1463        # Xcode universal build linker flags when targeting 64-bit OSX with LuaJIT enabled
1464        list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=x86_64] "${LUAJIT_EXE_LINKER_FLAGS_APPLE} $(OTHER_LDFLAGS)")
1465    endif ()
1466    _setup_target ()
1467
1468    if (URHO3D_SCP_TO_TARGET)
1469        add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND scp $<TARGET_FILE:${TARGET_NAME}> ${URHO3D_SCP_TO_TARGET} || exit 0
1470            COMMENT "Scp-ing ${TARGET_NAME} executable to target system")
1471    endif ()
1472    if (WIN32 AND NOT ARG_NODEPS AND URHO3D_LIB_TYPE STREQUAL SHARED)
1473        # Make a copy of the Urho3D DLL to the runtime directory in the build tree
1474        if (TARGET Urho3D)
1475            add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Urho3D> ${RUNTIME_DIR})
1476            add_make_clean_files (${RUNTIME_DIR}/$<TARGET_FILE_NAME:Urho3D>)
1477        else ()
1478            foreach (DLL ${URHO3D_DLL})
1479                add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DLL} ${RUNTIME_DIR})
1480                add_make_clean_files (${RUNTIME_DIR}/${DLL})
1481            endforeach ()
1482        endif ()
1483    endif ()
1484    if (DIRECT3D_DLL AND NOT ARG_NODEPS)
1485        # Make a copy of the D3D DLL to the runtime directory in the build tree
1486        add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DIRECT3D_DLL} ${RUNTIME_DIR})
1487        add_make_clean_files (${RUNTIME_DIR}/${DIRECT3D_DLL})
1488    endif ()
1489    # Need to check if the destination variable is defined first because this macro could be called by downstream project that does not wish to install anything
1490    if (NOT ARG_PRIVATE)
1491        if (WEB AND DEST_BUNDLE_DIR)
1492            set (EXTS data html.map js wasm)
1493            if (SELF_EXECUTABLE_SHELL)
1494                # Install it as program so it gets the correct file permission
1495                install (PROGRAMS $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${DEST_BUNDLE_DIR})
1496            else ()
1497                list (APPEND EXTS html)
1498            endif ()
1499            set (LOCATION $<TARGET_FILE_DIR:${TARGET_NAME}>)
1500            unset (FILES)
1501            foreach (EXT ${EXTS})
1502                list (APPEND FILES ${LOCATION}/${TARGET_NAME}.${EXT})
1503            endforeach ()
1504            install (FILES ${FILES} DESTINATION ${DEST_BUNDLE_DIR} OPTIONAL)
1505        elseif (DEST_RUNTIME_DIR AND (DEST_BUNDLE_DIR OR NOT (IOS OR TVOS)))
1506            install (TARGETS ${TARGET_NAME} RUNTIME DESTINATION ${DEST_RUNTIME_DIR} BUNDLE DESTINATION ${DEST_BUNDLE_DIR})
1507            if (WIN32 AND NOT ARG_NODEPS AND URHO3D_LIB_TYPE STREQUAL SHARED AND NOT URHO3D_DLL_INSTALLED)
1508                if (TARGET Urho3D)
1509                    install (FILES $<TARGET_FILE:Urho3D> DESTINATION ${DEST_RUNTIME_DIR})
1510                else ()
1511                    install (FILES ${URHO3D_DLL} DESTINATION ${DEST_RUNTIME_DIR})
1512                endif ()
1513                set (URHO3D_DLL_INSTALLED TRUE)
1514            endif ()
1515            if (DIRECT3D_DLL AND NOT DIRECT3D_DLL_INSTALLED)
1516                # Make a copy of the D3D DLL to the runtime directory in the installed location
1517                install (FILES ${DIRECT3D_DLL} DESTINATION ${DEST_RUNTIME_DIR})
1518                set (DIRECT3D_DLL_INSTALLED TRUE)
1519            endif ()
1520        endif ()
1521    endif ()
1522endmacro ()
1523
1524# Macro for setting up a library target
1525# Macro arguments:
1526#  NODEPS - setup library target without defining Urho3D dependency libraries (applicable for downstream projects)
1527#  STATIC/SHARED/MODULE/EXCLUDE_FROM_ALL - see CMake help on add_library() command
1528# CMake variables:
1529#  SOURCE_FILES - list of source files
1530#  INCLUDE_DIRS - list of directories for include search path
1531#  LIBS - list of dependent libraries that are built internally in the project
1532#  ABSOLUTE_PATH_LIBS - list of dependent libraries that are external to the project
1533#  LINK_DEPENDS - list of additional files on which a target binary depends for linking (Makefile-based generator only)
1534#  LINK_FLAGS - list of additional link flags
1535#  TARGET_PROPERTIES - list of target properties
1536macro (setup_library)
1537    cmake_parse_arguments (ARG NODEPS "" "" ${ARGN})
1538    check_source_files ()
1539    add_library (${TARGET_NAME} ${ARG_UNPARSED_ARGUMENTS} ${SOURCE_FILES})
1540    get_target_property (LIB_TYPE ${TARGET_NAME} TYPE)
1541    if (NOT ARG_NODEPS AND NOT PROJECT_NAME STREQUAL Urho3D)
1542        define_dependency_libs (Urho3D)
1543    endif ()
1544    if (XCODE AND LUAJIT_SHARED_LINKER_FLAGS_APPLE AND LIB_TYPE STREQUAL SHARED_LIBRARY)
1545        list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=x86_64] "${LUAJIT_SHARED_LINKER_FLAGS_APPLE} $(OTHER_LDFLAGS)")    # Xcode universal build linker flags when targeting 64-bit OSX with LuaJIT enabled
1546    endif ()
1547    _setup_target ()
1548
1549    if (PROJECT_NAME STREQUAL Urho3D)
1550        # Accumulate all the dependent static libraries that are used in building the Urho3D library itself
1551        if (NOT ${TARGET_NAME} STREQUAL Urho3D AND LIB_TYPE STREQUAL STATIC_LIBRARY)
1552            set (STATIC_LIBRARY_TARGETS ${STATIC_LIBRARY_TARGETS} ${TARGET_NAME} PARENT_SCOPE)
1553            # When performing Xcode CI build suppress all the warnings for 3rd party libraries because there are just too many of them
1554            if (XCODE AND DEFINED ENV{CI})
1555                set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
1556                set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
1557            endif ()
1558        endif ()
1559    elseif (URHO3D_SCP_TO_TARGET)
1560        add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND scp $<TARGET_FILE:${TARGET_NAME}> ${URHO3D_SCP_TO_TARGET} || exit 0
1561            COMMENT "Scp-ing ${TARGET_NAME} library to target system")
1562    endif ()
1563endmacro ()
1564
1565# Macro for setting up an executable target with resources to copy/package/bundle/preload
1566# Macro arguments:
1567#  NODEPS - setup executable target without defining Urho3D dependency libraries
1568#  NOBUNDLE - do not use MACOSX_BUNDLE even when URHO3D_MACOSX_BUNDLE build option is enabled
1569#  WIN32/MACOSX_BUNDLE/EXCLUDE_FROM_ALL - see CMake help on add_executable() command
1570# CMake variables:
1571#  RESOURCE_DIRS - list of resource directories (will be packaged into *.pak when URHO3D_PACKAGING build option is set)
1572#  RESOURCE_FILES - list of additional resource files (will not be packaged into *.pak in any case)
1573#  SOURCE_FILES - list of source files
1574#  INCLUDE_DIRS - list of directories for include search path
1575#  LIBS - list of dependent libraries that are built internally in the project
1576#  ABSOLUTE_PATH_LIBS - list of dependent libraries that are external to the project
1577#  LINK_DEPENDS - list of additional files on which a target binary depends for linking (Makefile-based generator only)
1578#  LINK_FLAGS - list of additional link flags
1579#  TARGET_PROPERTIES - list of target properties
1580macro (setup_main_executable)
1581    cmake_parse_arguments (ARG "NOBUNDLE;MACOSX_BUNDLE;WIN32" "" "" ${ARGN})
1582    if (NOT RESOURCE_DIRS)
1583        define_resource_dirs ()
1584    endif ()
1585    if (ANDROID)
1586        # Add SDL native init function, SDL_Main() entry point must be defined by one of the source files in ${SOURCE_FILES}
1587        find_Urho3D_file (ANDROID_MAIN_C_PATH SDL_android_main.c
1588            HINTS ${URHO3D_HOME}/include/Urho3D/ThirdParty/SDL/android ${CMAKE_SOURCE_DIR}/Source/ThirdParty/SDL/src/main/android
1589            DOC "Path to SDL_android_main.c" MSG_MODE FATAL_ERROR)
1590        list (APPEND SOURCE_FILES ${ANDROID_MAIN_C_PATH})
1591        # Setup shared library output path
1592        set_output_directories (${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME} LIBRARY)
1593        # Setup target as main shared library
1594        setup_library (SHARED)
1595        if (DEST_LIBRARY_DIR)
1596            install (TARGETS ${TARGET_NAME} LIBRARY DESTINATION ${DEST_LIBRARY_DIR} ARCHIVE DESTINATION ${DEST_LIBRARY_DIR})
1597        endif ()
1598        # Copy other dependent shared libraries to Android library output path
1599        if (ANDROID_STL MATCHES shared)
1600            # Android toolchain may already copy a shared C++ STL runtime to library output path,
1601            # still we configure another post build command to copy the runtime and its clean up here for consistency sake
1602            add_custom_command (TARGET ${TARGET_NAME} POST_BUILD
1603                COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${STL_LIBRARY_DIR}/lib${ANDROID_STL}.so ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/lib${ANDROID_STL}.so)
1604            add_make_clean_files (${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/lib${ANDROID_STL}.so)
1605        endif ()
1606        foreach (FILE ${ABSOLUTE_PATH_LIBS})
1607            get_filename_component (EXT ${FILE} EXT)
1608            if (EXT STREQUAL .so)
1609                get_filename_component (NAME ${FILE} NAME)
1610                add_custom_command (TARGET ${TARGET_NAME} POST_BUILD
1611                    COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${FILE} ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}
1612                    COMMENT "Copying ${NAME} to library output directory")
1613                add_make_clean_files (${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/${NAME})
1614            endif ()
1615        endforeach ()
1616        if (ANDROID_NDK_GDB)
1617            # Copy the library while it still has debug symbols for ndk-gdb
1618            add_custom_command (TARGET ${TARGET_NAME} POST_BUILD
1619                COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${TARGET_NAME}> ${NDK_GDB_SOLIB_PATH}
1620                COMMENT "Copying lib${TARGET_NAME}.so with debug symbols to ${NDK_GDB_SOLIB_PATH} directory")
1621            add_make_clean_files (${NDK_GDB_SOLIB_PATH}/$<TARGET_FILE_NAME:${TARGET_NAME}>)
1622        endif ()
1623        # When performing packaging, include the final apk file
1624        if (CMAKE_PROJECT_NAME STREQUAL Urho3D AND NOT APK_INCLUDED)
1625            install (FILES ${LIBRARY_OUTPUT_PATH_ROOT}/bin/Urho3D-debug.apk DESTINATION ${DEST_RUNTIME_DIR} OPTIONAL)
1626            set (APK_INCLUDED 1)
1627        endif ()
1628    else ()
1629        # Setup target as executable
1630        if (WIN32)
1631            if (NOT URHO3D_WIN32_CONSOLE OR ARG_WIN32)
1632                set (EXE_TYPE WIN32)
1633            endif ()
1634            list (APPEND TARGET_PROPERTIES DEBUG_POSTFIX _d)
1635        elseif (IOS)
1636            set (EXE_TYPE MACOSX_BUNDLE)
1637            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 1,2 MACOSX_BUNDLE_INFO_PLIST iOSBundleInfo.plist.template)
1638        elseif (TVOS)
1639            set (EXE_TYPE MACOSX_BUNDLE)
1640            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 3 MACOSX_BUNDLE_INFO_PLIST tvOSBundleInfo.plist.template)
1641        elseif (APPLE)
1642            if ((URHO3D_MACOSX_BUNDLE OR ARG_MACOSX_BUNDLE) AND NOT ARG_NOBUNDLE)
1643                set (EXE_TYPE MACOSX_BUNDLE)
1644                list (APPEND TARGET_PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.template)
1645            endif ()
1646        elseif (WEB)
1647            if (EMSCRIPTEN)
1648                # Output to HTML when a HTML shell-file is being added in source files list
1649                foreach (FILE ${SOURCE_FILES})
1650                    get_property (EMCC_OPTION SOURCE ${FILE} PROPERTY EMCC_OPTION)
1651                    if (EMCC_OPTION STREQUAL shell-file)
1652                        list (APPEND TARGET_PROPERTIES SUFFIX .html)
1653                        # Check if the shell-file is self-executable
1654                        file (READ ${FILE} SHEBANG LIMIT 3)     # Workaround CMake's funny way of file I/O operation
1655                        string (COMPARE EQUAL ${SHEBANG} "#!\n" SELF_EXECUTABLE_SHELL)
1656                        set (HAS_SHELL_FILE 1)
1657                        break ()
1658                    endif ()
1659                endforeach ()
1660                if (URHO3D_TESTING)
1661                    # Auto adding the HTML shell-file during testing with emrun, if it has not been added yet
1662                    if (NOT EMCC_OPTION STREQUAL shell-file)
1663                        add_html_shell ()
1664                        list (APPEND TARGET_PROPERTIES SUFFIX .html)
1665                        set (SELF_EXECUTABLE_SHELL 1)
1666                        set (HAS_SHELL_FILE 1)
1667                    endif ()
1668                endif ()
1669            endif ()
1670        endif ()
1671        setup_executable (${EXE_TYPE} ${ARG_UNPARSED_ARGUMENTS})
1672        if (HAS_SHELL_FILE)
1673            get_target_property (LOCATION ${TARGET_NAME} LOCATION)
1674            get_filename_component (NAME_WE ${LOCATION} NAME_WE)
1675            add_make_clean_files ($<TARGET_FILE_DIR:${TARGET_NAME}>/${NAME_WE}.js $<TARGET_FILE_DIR:${TARGET_NAME}>/${NAME_WE}.wasm)
1676        endif ()
1677    endif ()
1678    # Setup custom resource checker target
1679    if ((EXE_TYPE STREQUAL MACOSX_BUNDLE OR URHO3D_PACKAGING) AND RESOURCE_DIRS)
1680        if (URHO3D_PACKAGING)
1681            # Urho3D project builds the PackageTool as required; downstream project uses PackageTool found in the Urho3D build tree or Urho3D SDK
1682            find_Urho3d_tool (PACKAGE_TOOL PackageTool
1683                HINTS ${CMAKE_BINARY_DIR}/bin/tool ${URHO3D_HOME}/bin/tool
1684                DOC "Path to PackageTool" MSG_MODE WARNING)
1685            if (CMAKE_PROJECT_NAME STREQUAL Urho3D)
1686                set (PACKAGING_DEP DEPENDS PackageTool)
1687            endif ()
1688            set (PACKAGING_COMMENT " and packaging")
1689        endif ()
1690        # Share a same custom target that checks for a same resource dirs list
1691        foreach (DIR ${RESOURCE_DIRS})
1692            string (MD5 MD5 ${DIR})
1693            set (MD5ALL ${MD5ALL}${MD5})
1694            if (CMAKE_HOST_WIN32)
1695                # On Windows host, always assumes there are changes so resource dirs would be repackaged in each build, however, still make sure the *.pak timestamp is not altered unnecessarily
1696                if (URHO3D_PACKAGING)
1697                    set (PACKAGING_COMMAND && echo Packaging ${DIR}... && ${PACKAGE_TOOL} ${DIR} ${RESOURCE_${DIR}_PATHNAME}.new -c -q && ${CMAKE_COMMAND} -E copy_if_different ${RESOURCE_${DIR}_PATHNAME}.new ${RESOURCE_${DIR}_PATHNAME} && ${CMAKE_COMMAND} -E remove ${RESOURCE_${DIR}_PATHNAME}.new)
1698                endif ()
1699                list (APPEND COMMANDS COMMAND ${CMAKE_COMMAND} -E touch ${DIR} ${PACKAGING_COMMAND})
1700            else ()
1701                # On Unix-like hosts, detect the changes in the resource directory recursively so they are only repackaged and/or rebundled (Xcode only) as necessary
1702                if (URHO3D_PACKAGING)
1703                    set (PACKAGING_COMMAND && echo Packaging ${DIR}... && ${PACKAGE_TOOL} ${DIR} ${RESOURCE_${DIR}_PATHNAME} -c -q)
1704                    set (OUTPUT_COMMAND test -e ${RESOURCE_${DIR}_PATHNAME} || \( true ${PACKAGING_COMMAND} \))
1705                else ()
1706                    set (OUTPUT_COMMAND true)   # Nothing to output
1707                endif ()
1708                list (APPEND COMMANDS COMMAND echo Checking ${DIR}... && bash -c \"\(\( `find ${DIR} -newer ${DIR} |wc -l` \)\)\" && touch -cm ${DIR} ${PACKAGING_COMMAND} || ${OUTPUT_COMMAND})
1709            endif ()
1710            add_make_clean_files (${RESOURCE_${DIR}_PATHNAME})
1711        endforeach ()
1712        string (MD5 MD5ALL ${MD5ALL})
1713        # Ensure the resource check is done before building the main executable target
1714        if (NOT RESOURCE_CHECK_${MD5ALL})
1715            set (RESOURCE_CHECK RESOURCE_CHECK)
1716            while (TARGET ${RESOURCE_CHECK})
1717                string (RANDOM RANDOM)
1718                set (RESOURCE_CHECK RESOURCE_CHECK_${RANDOM})
1719            endwhile ()
1720            set (RESOURCE_CHECK_${MD5ALL} ${RESOURCE_CHECK} CACHE INTERNAL "Resource check hash map")
1721        endif ()
1722        if (NOT TARGET ${RESOURCE_CHECK_${MD5ALL}})
1723            add_custom_target (${RESOURCE_CHECK_${MD5ALL}} ALL ${COMMANDS} ${PACKAGING_DEP} COMMENT "Checking${PACKAGING_COMMENT} resource directories")
1724        endif ()
1725        add_dependencies (${TARGET_NAME} ${RESOURCE_CHECK_${MD5ALL}})
1726    endif ()
1727    # Only need to install the resource directories once in case they are referenced by multiple targets
1728    if (RESOURCE_DIRS AND DEST_SHARE_DIR)
1729        foreach (DIR ${RESOURCE_DIRS})
1730            list (FIND INSTALLED_RESOURCE_DIRS ${DIR} FOUND_INDEX)
1731            if (FOUND_INDEX EQUAL -1)
1732                install (DIRECTORY ${DIR} DESTINATION ${DEST_SHARE_DIR}/Resources)
1733                list (APPEND INSTALLED_RESOURCE_DIRS ${DIR})
1734            endif ()
1735            # This cache variable is used to keep track of whether a resource directory has been instructed to be installed by CMake or not
1736            set (INSTALLED_RESOURCE_DIRS ${INSTALLED_RESOURCE_DIRS} CACHE INTERNAL "Installed resource dirs")
1737        endforeach ()
1738    endif ()
1739    # Define a custom command for stripping the main target executable (or shared library for Android) for Release build configuration
1740    # Exclude multi-config generators, plus MSVC explicitly since it could also be used through NMake which is not multi-config,
1741    # but MSVC does not have a strip command
1742    if (CMAKE_BUILD_TYPE STREQUAL Release AND NOT WEB AND NOT MSVC)
1743        add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${TARGET_NAME}>)
1744    endif ()
1745endmacro ()
1746
1747# This cache variable is used to keep track of whether a resource directory has been instructed to be installed by CMake or not
1748unset (INSTALLED_RESOURCE_DIRS CACHE)
1749
1750# Macro for setting up dependency lib for compilation and linking of a target (to be used internally)
1751macro (_setup_target)
1752    # Include directories
1753    include_directories (${INCLUDE_DIRS})
1754    # Link libraries
1755    define_dependency_libs (${TARGET_NAME})
1756    target_link_libraries (${TARGET_NAME} ${ABSOLUTE_PATH_LIBS} ${LIBS})
1757    # Enable PCH if requested
1758    if (${TARGET_NAME}_HEADER_PATHNAME)
1759        enable_pch (${${TARGET_NAME}_HEADER_PATHNAME})
1760    endif ()
1761    # Extra compiler flags for Xcode which are dynamically changed based on active arch in order to support Mach-O universal binary targets
1762    # We don't add the ABI flag for Xcode because it automatically passes '-arch i386' compiler flag when targeting 32 bit which does the same thing as '-m32'
1763    if (XCODE)
1764        # Speed up build when in Debug configuration by building active arch only
1765        list (FIND TARGET_PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH ATTRIBUTE_ALREADY_SET)
1766        if (ATTRIBUTE_ALREADY_SET EQUAL -1)
1767            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$<CONFIG:Debug>:YES>)
1768        endif ()
1769        if (NOT URHO3D_SSE)
1770            # Nullify the Clang default so that it is consistent with GCC
1771            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=i386] "-mno-sse $(OTHER_CFLAGS)")
1772            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=i386] "-mno-sse $(OTHER_CPLUSPLUSFLAGS)")
1773        endif ()
1774    endif ()
1775    # Extra linker flags for Emscripten
1776    if (EMSCRIPTEN)
1777        # These flags are set only once either in the main module or main executable
1778        if ((URHO3D_LIB_TYPE STREQUAL MODULE AND ${TARGET_NAME} STREQUAL Urho3D) OR (NOT URHO3D_LIB_TYPE STREQUAL MODULE AND NOT LIB_TYPE))
1779            list (APPEND LINK_FLAGS "-s TOTAL_MEMORY=${EMSCRIPTEN_TOTAL_MEMORY}")
1780            if (EMSCRIPTEN_ALLOW_MEMORY_GROWTH)
1781                list (APPEND LINK_FLAGS "-s ALLOW_MEMORY_GROWTH=1")
1782            endif ()
1783            if (EMSCRIPTEN_SHARE_DATA)      # MODULE lib type always have this variable enabled
1784                list (APPEND LINK_FLAGS "--pre-js \"${CMAKE_BINARY_DIR}/Source/pak-loader.js\"")
1785            endif ()
1786            if (URHO3D_TESTING)
1787                list (APPEND LINK_FLAGS --emrun)
1788            else ()
1789                # If not using EMRUN then we need to include the emrun_prejs.js manually in order to process the request parameters as app's arguments correctly
1790                list (APPEND LINK_FLAGS "--pre-js \"${EMSCRIPTEN_ROOT_PATH}/src/emrun_prejs.js\"")
1791            endif ()
1792        endif ()
1793        # These flags are here instead of in the CMAKE_(EXE|MODULE)_LINKER_FLAGS so that they do not interfere with the auto-detection logic during initial configuration
1794        if (NOT LIB_TYPE OR LIB_TYPE STREQUAL MODULE)
1795            list (APPEND LINK_FLAGS "-s NO_EXIT_RUNTIME=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1")
1796            if (EMSCRIPTEN_WASM)
1797                list (APPEND LINK_FLAGS "-s WASM=1")
1798            endif ()
1799        endif ()
1800        # Pass EMCC-specifc setting to differentiate between main and side modules
1801        if (URHO3D_LIB_TYPE STREQUAL MODULE)
1802            if (${TARGET_NAME} STREQUAL Urho3D)
1803                # Main module has standard libs statically linked
1804                list (APPEND LINK_FLAGS "-s MAIN_MODULE=1")
1805            elseif ((NOT ARG_NODEPS AND NOT LIB_TYPE) OR LIB_TYPE STREQUAL MODULE)
1806                if (LIB_TYPE)
1807                    set (SIDE_MODULES ${SIDE_MODULES} ${TARGET_NAME} PARENT_SCOPE)
1808                endif ()
1809                # Also consider the executable target as another side module but only this scope
1810                list (APPEND LINK_FLAGS "-s SIDE_MODULE=1")
1811                list (APPEND SIDE_MODULES ${TARGET_NAME})
1812                # Define custom commands for post processing the output file to first load the main module before the side module(s)
1813                add_custom_command (TARGET ${TARGET_NAME} POST_BUILD
1814                    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<$<STREQUAL:${URHO3D_LIBRARIES},Urho3D>:$<TARGET_FILE:Urho3D>>$<$<NOT:$<STREQUAL:${URHO3D_LIBRARIES},Urho3D>>:${URHO3D_LIBRARIES}> $<TARGET_FILE_DIR:${TARGET_NAME}>
1815                    COMMAND ${CMAKE_COMMAND} -E $<$<NOT:$<CONFIG:Debug>>:echo> copy_if_different $<$<STREQUAL:${URHO3D_LIBRARIES},Urho3D>:$<TARGET_FILE:Urho3D>.map>$<$<NOT:$<STREQUAL:${URHO3D_LIBRARIES},Urho3D>>:${URHO3D_LIBRARIES}.map> $<TARGET_FILE_DIR:${TARGET_NAME}> $<$<NOT:$<CONFIG:Debug>>:$<ANGLE-R>${NULL_DEVICE}>
1816                    COMMAND ${CMAKE_COMMAND} -DTARGET_NAME=${TARGET_NAME} -DTARGET_FILE=$<TARGET_FILE:${TARGET_NAME}> -DTARGET_DIR=$<TARGET_FILE_DIR:${TARGET_NAME}> -DHAS_SHELL_FILE=${HAS_SHELL_FILE} -DSIDE_MODULES="${SIDE_MODULES}" -P ${CMAKE_SOURCE_DIR}/CMake/Modules/PostProcessForWebModule.cmake)
1817                add_make_clean_files ($<TARGET_FILE_DIR:${TARGET_NAME}>/libUrho3D.js $<TARGET_FILE_DIR:${TARGET_NAME}>/libUrho3D.js.map)
1818            endif ()
1819        endif ()
1820        # Pass additional source files to linker with the supported flags, such as: js-library, pre-js, post-js, embed-file, preload-file, shell-file
1821        foreach (FILE ${SOURCE_FILES})
1822            get_property (EMCC_OPTION SOURCE ${FILE} PROPERTY EMCC_OPTION)
1823            if (EMCC_OPTION)
1824                unset (EMCC_FILE_ALIAS)
1825                unset (EMCC_EXCLUDE_FILE)
1826                unset (USE_PRELOAD_CACHE)
1827                if (EMCC_OPTION STREQUAL embed-file OR EMCC_OPTION STREQUAL preload-file)
1828                    get_property (EMCC_FILE_ALIAS SOURCE ${FILE} PROPERTY EMCC_FILE_ALIAS)
1829                    if (EMCC_FILE_ALIAS)
1830                        set (EMCC_FILE_ALIAS "@\"${EMCC_FILE_ALIAS}\"")
1831                    endif ()
1832                    get_property (EMCC_EXCLUDE_FILE SOURCE ${FILE} PROPERTY EMCC_EXCLUDE_FILE)
1833                    if (EMCC_EXCLUDE_FILE)
1834                        set (EMCC_EXCLUDE_FILE " --exclude-file \"${EMCC_EXCLUDE_FILE}\"")
1835                    else ()
1836                        list (APPEND LINK_DEPENDS ${FILE})
1837                    endif ()
1838                    if (EMCC_OPTION STREQUAL preload-file)
1839                        set (USE_PRELOAD_CACHE " --use-preload-cache")
1840                    endif ()
1841                endif ()
1842                list (APPEND LINK_FLAGS "--${EMCC_OPTION} \"${FILE}\"${EMCC_FILE_ALIAS}${EMCC_EXCLUDE_FILE}${USE_PRELOAD_CACHE}")
1843            endif ()
1844        endforeach ()
1845        # If it is a self-executable shell-file then change the file permission of the output file accordingly
1846        if (SELF_EXECUTABLE_SHELL AND NOT CMAKE_HOST_WIN32)
1847            add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND chmod +x $<TARGET_FILE:${TARGET_NAME}>)
1848        endif ()
1849    endif ()
1850    # Set additional linker dependencies (only work for Makefile-based generator according to CMake documentation)
1851    if (LINK_DEPENDS)
1852        string (REPLACE ";" "\;" LINK_DEPENDS "${LINK_DEPENDS}")        # Stringify for string replacement
1853        list (APPEND TARGET_PROPERTIES LINK_DEPENDS "${LINK_DEPENDS}")  # Stringify with semicolons already escaped
1854        unset (LINK_DEPENDS)
1855    endif ()
1856    # Set additional linker flags
1857    if (LINK_FLAGS)
1858        string (REPLACE ";" " " LINK_FLAGS "${LINK_FLAGS}")
1859        list (APPEND TARGET_PROPERTIES LINK_FLAGS ${LINK_FLAGS})
1860        unset (LINK_FLAGS)
1861    endif ()
1862    if (TARGET_PROPERTIES)
1863        set_target_properties (${TARGET_NAME} PROPERTIES ${TARGET_PROPERTIES})
1864        unset (TARGET_PROPERTIES)
1865    endif ()
1866    # Create symbolic links in the build tree
1867    if (ANDROID)
1868        foreach (I AndroidManifest.xml build.xml custom_rules.xml project.properties src res assets jni)
1869            if (EXISTS ${CMAKE_SOURCE_DIR}/Android/${I} AND NOT EXISTS ${CMAKE_BINARY_DIR}/${I})    # No-ops when 'Android' is used as build tree
1870                create_symlink (${CMAKE_SOURCE_DIR}/Android/${I} ${CMAKE_BINARY_DIR}/${I} FALLBACK_TO_COPY)
1871            endif ()
1872        endforeach ()
1873        set (ASSET_ROOT assets)
1874    else ()
1875        set (ASSET_ROOT bin)
1876    endif ()
1877    if (NOT URHO3D_PACKAGING)
1878        # Ensure the asset root directory exist before creating the symlinks
1879        file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${ASSET_ROOT})
1880        foreach (I ${RESOURCE_DIRS})
1881            get_filename_component (NAME ${I} NAME)
1882            if (NOT EXISTS ${CMAKE_BINARY_DIR}/${ASSET_ROOT}/${NAME} AND EXISTS ${I})
1883                create_symlink (${I} ${CMAKE_BINARY_DIR}/${ASSET_ROOT}/${NAME} FALLBACK_TO_COPY)
1884            endif ()
1885        endforeach ()
1886    endif ()
1887    # Workaround CMake/Xcode generator bug where it always appends '/build' path element to SYMROOT attribute and as such the items in Products are always rendered as red in the Xcode as if they are not yet built
1888    if (NOT DEFINED ENV{TRAVIS})
1889        if (XCODE AND NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
1890            file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/build)
1891            get_target_property (LOCATION ${TARGET_NAME} LOCATION)
1892            string (REGEX REPLACE "^.*\\$\\(CONFIGURATION\\)" $(CONFIGURATION) SYMLINK ${LOCATION})
1893            get_filename_component (DIRECTORY ${SYMLINK} PATH)
1894            add_custom_command (TARGET ${TARGET_NAME} POST_BUILD
1895                COMMAND mkdir -p ${DIRECTORY} && ln -sf $<TARGET_FILE:${TARGET_NAME}> ${DIRECTORY}/$<TARGET_FILE_NAME:${TARGET_NAME}>
1896                WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/build)
1897        endif ()
1898    endif ()
1899endmacro()
1900
1901# Macro for setting up a test case
1902macro (setup_test)
1903    if (URHO3D_TESTING)
1904        cmake_parse_arguments (ARG "" NAME OPTIONS ${ARGN})
1905        if (NOT ARG_NAME)
1906            set (ARG_NAME ${TARGET_NAME})
1907        endif ()
1908        list (APPEND ARG_OPTIONS -timeout ${URHO3D_TEST_TIMEOUT})
1909        if (WEB)
1910            if (EMSCRIPTEN)
1911                math (EXPR EMRUN_TIMEOUT "2 * ${URHO3D_TEST_TIMEOUT}")
1912                add_test (NAME ${ARG_NAME} COMMAND ${EMRUN} --browser ${EMSCRIPTEN_EMRUN_BROWSER} --timeout ${EMRUN_TIMEOUT} --kill_exit ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET_NAME}.html ${ARG_OPTIONS})
1913            endif ()
1914        else ()
1915            add_test (NAME ${ARG_NAME} COMMAND ${TARGET_NAME} ${ARG_OPTIONS})
1916        endif ()
1917    endif ()
1918endmacro ()
1919
1920# Set common binary output directory if not already set (note that this module can be included in an external project which may already have DEST_RUNTIME_DIR preset)
1921if (NOT DEST_RUNTIME_DIR)
1922    set_output_directories (${CMAKE_BINARY_DIR}/bin RUNTIME PDB)
1923endif ()
1924
1925if (ANDROID)
1926    # TODO: Verify if this setup still works with Android NDK 13 and above
1927    # Enable Android ndk-gdb, if the build option is enabled
1928    if (ANDROID_NDK_GDB)
1929        set (NDK_GDB_SOLIB_PATH ${CMAKE_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
1930        file (MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
1931        set (NDK_GDB_JNI ${CMAKE_BINARY_DIR}/jni)
1932        set (NDK_GDB_MK "# This is a generated file. DO NOT EDIT!\n\nAPP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
1933        foreach (MK Android.mk Application.mk)
1934            if (NOT EXISTS ${NDK_GDB_JNI}/${MK})
1935                file (WRITE ${NDK_GDB_JNI}/${MK} ${NDK_GDB_MK})
1936            endif ()
1937        endforeach ()
1938        get_directory_property (INCLUDE_DIRECTORIES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
1939        string (REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}")   # Note: need to always "stringify" a variable in list context for replace to work correctly
1940        set (NDK_GDB_SETUP "# This is a generated file. DO NOT EDIT!\n\nset solib-search-path ${NDK_GDB_SOLIB_PATH}\ndirectory ${INCLUDE_DIRECTORIES}\n")
1941        file (WRITE ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup ${NDK_GDB_SETUP})
1942        file (COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME})
1943    else ()
1944        file (REMOVE ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdbserver)
1945    endif ()
1946elseif (WEB)
1947    if (EMSCRIPTEN_SHARE_DATA AND NOT EXISTS ${CMAKE_BINARY_DIR}/Source/pak-loader.js)
1948        file (WRITE ${CMAKE_BINARY_DIR}/Source/pak-loader.js "var Module;if(typeof Module==='undefined')Module=eval('(function(){try{return Module||{}}catch(e){return{}}})()');var s=document.createElement('script');s.src='${CMAKE_PROJECT_NAME}.js';document.body.appendChild(s);Module['preRun'].push(function(){Module['addRunDependency']('${CMAKE_PROJECT_NAME}.js.loader')});s.onload=function(){Module['removeRunDependency']('${CMAKE_PROJECT_NAME}.js.loader')};")
1949    endif ()
1950endif ()
1951
1952# Warn user if PATH environment variable has not been correctly set for using ccache
1953if (NOT CMAKE_HOST_WIN32 AND "$ENV{USE_CCACHE}")
1954    if (APPLE)
1955        set (WHEREIS brew info ccache)
1956    else ()
1957        set (WHEREIS whereis -b ccache)
1958    endif ()
1959    execute_process (COMMAND ${WHEREIS} COMMAND grep -o \\S*lib\\S* RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
1960    if (EXIT_CODE EQUAL 0 AND NOT $ENV{PATH} MATCHES "${CCACHE_SYMLINK}")  # Need to stringify because CCACHE_SYMLINK variable could be empty when the command failed
1961        message (WARNING "The lib directory containing the ccache symlinks (${CCACHE_SYMLINK}) has not been added in the PATH environment variable. "
1962            "This is required to enable ccache support for native compiler toolchain. CMake has been configured to use the actual compiler toolchain instead of ccache. "
1963            "In order to rectify this, the build tree must be regenerated after the PATH environment variable has been adjusted accordingly.")
1964    endif ()
1965endif ()
1966
1967# Post-CMake fixes
1968if (IOS)
1969    # TODO: can be removed when CMake minimum required has reached 3.4
1970    if (CMAKE_VERSION VERSION_LESS 3.4)
1971        # Due to a bug in the CMake/Xcode generator (fixed in 3.4) that prevents iOS targets (library and bundle) to be installed correctly
1972        # (see http://public.kitware.com/Bug/bug_relationship_graph.php?bug_id=12506&graph=dependency),
1973        # below temporary fix is required to work around the bug
1974        list (APPEND POST_CMAKE_FIXES COMMAND sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' ${CMAKE_BINARY_DIR}/CMakeScripts/install_postBuildPhase.make* || exit 0)
1975    endif ()
1976elseif (TVOS)
1977    # Almost the same bug as iOS one above but not quite, most probably because CMake does not support AppleTV platform yet
1978    list (APPEND POST_CMAKE_FIXES COMMAND sed -i '' 's/\)\$$\(EFFECTIVE_PLATFORM_NAME\)/\) -DEFFECTIVE_PLATFORM_NAME=$$\(EFFECTIVE_PLATFORM_NAME\)/g' ${CMAKE_BINARY_DIR}/CMakeScripts/install_postBuildPhase.make* || exit 0)
1979    add_custom_target (APPLETV_POST_CMAKE_FIX COMMAND sed -i '' -E 's,\(Debug|RelWithDebInfo|Release\)/,$$\(CONFIGURATION\)$$\(EFFECTIVE_PLATFORM_NAME\)/,g' ${CMAKE_BINARY_DIR}/Source/Urho3D/CMakeScripts/Urho3D_cmakeRulesBuildPhase.make* || exit 0)
1980endif ()
1981if (POST_CMAKE_FIXES)
1982    add_custom_target (POST_CMAKE_FIXES ALL ${POST_CMAKE_FIXES} COMMENT "Applying post-cmake fixes")
1983endif ()
1984