if(NOT OS_DETECTED)

message(STATUS "Detecting OS")

# Detect target OS
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
	# WIN32 is TRUE on Windows, including Cygwin
	if(WIN32)
		if(UNIX)
			message(WARNING "OS identified as both Windows and Unix (Maybe Cygwin/MinGW?).")
		else()
			message(STATUS "OS identified as Windows.")
			set(CMAKE_OS "WINDOWS" CACHE STRING "Targetted OS" FORCE)
		endif()
	else()
		message(WARNING "OS identified as Windows, but WIN32 macro not set.")
	endif ()
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
	# UNIX is TRUE on all UNIX-like OS's, including Apple OS X and Cygwin.	
	if(UNIX)
		if(NOT ANDROID)
			message(STATUS "OS identified as Linux.")
			set(CMAKE_OS "LINUX" CACHE STRING "Targetted OS" FORCE)
		else()
			message(WARNING "OS identified as Linux, but ANDROID macro set.")
		endif()
	else()
		message(WARNING "OS identified as Linux, but UNIX macro not set.")
	endif ()	
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin" OR CMAKE_SYSTEM_NAME MATCHES "MacOS")
	# APPLE is TRUE on Apple systems and systems that have __APPLE__ macro defined
	if(APPLE)
		message(STATUS "OS indentified as MacOS/Darwin.")
		set(CMAKE_OS "MACOS" CACHE STRING "Targetted OS" FORCE)
	else()
		message(WARNING "OS indentified as MacOS/Darwin, but APPLE macro not set.")
	endif ()
elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
	if(ANDROID)
		message(STATUS "OS indentified as Android.")
		message(FATAL_ERROR "Android compilation not yet supported.")
		set(CMAKE_OS "ANDROID" CACHE STRING "Targetted OS" FORCE)
	else()
		message(WARNING "OS indentified as Android, but ANDROID macro is not set.")
	endif ()
elseif(CMAKE_SYSTEM_NAME MATCHES "iOS")
	if(IOS)
		message(STATUS "OS indentified as iOS.")
		message(FATAL_ERROR "iOS compilation not yet supported.")
		set(CMAKE_OS "IOS" CACHE STRING "Targetted OS" FORCE)
	else()
		message(WARNING "OS indentified as iOS, but IOS macro is not set.")
	endif ()
else()
	message(WARNING "OS is other than Windows, Linux, MacOS, Android, or iOS.")
endif()

if(NOT CMAKE_OS)
	message(FATAL_ERROR "Unsupported OS.")
endif()

# Detect 32-bit or 64-bit
if(CMAKE_SIZEOF_VOID_P STREQUAL "8")
	message(STATUS "Configuring for 64-bit architecture")
	set(PLATFORM_64BIT TRUE CACHE STRING "Targetted memory architecture" FORCE)
else ()
	message(FATAL_ERROR "32-bit memory architecture no longer supported.")
endif()

# Detect compiler
message(STATUS "Configuring for compiler: ${CMAKE_CXX_COMPILER_ID} (version ${CMAKE_CXX_COMPILER_VERSION})")

# Is Clang
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
	set(PLATFORM_COMPILER "CLANG" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "ARMClang")
	set(PLATFORM_COMPILER "CLANG" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
	set(PLATFORM_COMPILER "CLANG" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "XLClang")
	set(PLATFORM_COMPILER "CLANG" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
	set(PLATFORM_COMPILER "LLVM" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
	set(PLATFORM_COMPILER "MSVC" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
	set(PLATFORM_COMPILER "GCC" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
	set(PLATFORM_COMPILER "INTEL" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Emscripten")
	set(PLATFORM_COMPILER "EMSCRIPTEN" CACHE STRING "Targetted compiler" FORCE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "emscripten")
	set(PLATFORM_COMPILER "EMSCRIPTEN" CACHE STRING "Targetted compiler" FORCE)
else()
	message(WARNING "Unrecognized compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()

set(OS_DETECTED ON CACHE INTERNAL "Whether platform detection has been completed" FORCE)

else()
	message(STATUS "Skipping platform detection, already detected")
endif()