cmake_minimum_required(VERSION 3.4...3.28)

if (POLICY CMP0072)
        cmake_policy (SET CMP0072 OLD)
endif()
if (POLICY CMP0148)
        cmake_policy (SET CMP0148 OLD)
endif()

project (piglit)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules")

INCLUDE (GNUInstallDirs)
INCLUDE (CheckCCompilerFlag)
INCLUDE (CheckCSourceCompiles)
INCLUDE (CheckCXXCompilerFlag)
INCLUDE (CheckFunctionExists)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckIncludeFile)
INCLUDE (FindPkgConfig)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
	set(DEFAULT_EGL ON)
	set(DEFAULT_GLX ON)
	set(DEFAULT_WGL OFF)

	set(DEFAULT_WAFFLE ON)

	set(DEFAULT_GBM ON)
	set(DEFAULT_WAYLAND ON)
	set(DEFAULT_X11 ON)

	set(DEFAULT_GLES_TESTS_BUILD ON)
	set(DEFAULT_VK_TESTS_BUILD ON)
elseif(APPLE)
	set(DEFAULT_EGL OFF)
	set(DEFAULT_GLX OFF)
	set(DEFAULT_WGL OFF)

	set(DEFAULT_WAFFLE OFF)

	set(DEFAULT_GBM OFF)
	set(DEFAULT_WAYLAND OFF)
	set(DEFAULT_X11 OFF)

	set(DEFAULT_GLES_TESTS_BUILD OFF)
	set(DEFAULT_VK_TESTS_BUILD OFF)
elseif(WIN32)
	set(DEFAULT_EGL OFF)
	set(DEFAULT_GLX OFF)
	set(DEFAULT_WGL ON)

	set(DEFAULT_WAFFLE OFF)

	set(DEFAULT_GBM OFF)
	set(DEFAULT_WAYLAND OFF)
	set(DEFAULT_X11 OFF)

	set(DEFAULT_GLES_TESTS_BUILD OFF)
	set(DEFAULT_VK_TESTS_BUILD OFF)
else()
	message(FATAL_ERROR "Unsupported platform")
endif()

option(PIGLIT_SSE2 "Build with SSE2 support on 32-bit x86 architecture" ON)

option(PIGLIT_USE_WAFFLE "Use Waffle in place of GLUT" ${DEFAULT_WAFFLE})

option(PIGLIT_USE_GBM "Use GBM" ${DEFAULT_GBM})
option(PIGLIT_USE_WAYLAND "Use Wayland" ${DEFAULT_WAYLAND})
option(PIGLIT_USE_X11 "Use X11" ${DEFAULT_X11})

option(PIGLIT_BUILD_EGL_TESTS "Build tests that require EGL" ${DEFAULT_EGL})
option(PIGLIT_BUILD_GLX_TESTS "Build tests that require GLX" ${DEFAULT_GLX})
option(PIGLIT_BUILD_WGL_TESTS "Build tests that require WGL" ${DEFAULT_WGL})

option(PIGLIT_BUILD_GL_TESTS "Build tests for OpenGL" ON)
option(PIGLIT_BUILD_GLES1_TESTS "Build tests for OpenGL ES1" ${DEFAULT_GLES_TESTS_BUILD})
option(PIGLIT_BUILD_GLES2_TESTS "Build tests for OpenGL ES2" ${DEFAULT_GLES_TESTS_BUILD})
option(PIGLIT_BUILD_GLES3_TESTS "Build tests for OpenGL ES3" ${DEFAULT_GLES_TESTS_BUILD})
option(PIGLIT_BUILD_CL_TESTS "Build tests for OpenCL" OFF)
option(PIGLIT_BUILD_VK_TESTS "Build tests for Vulkan" ${DEFAULT_VK_TESTS_BUILD})

option(PIGLIT_BUILD_DMA_BUF_TESTS "Build tests that use dma_buf" ${DEFAULT_GBM})


find_package(Threads)
find_package(PNG)
if(PNG_FOUND)
	add_definitions(-DPIGLIT_HAS_PNG)
endif(PNG_FOUND)

if(PIGLIT_BUILD_GLX_TESTS AND NOT PIGLIT_USE_X11)
	message(FATAL_ERROR "X11 has to be enabled for GLX to build")
endif()

if(PIGLIT_BUILD_DMA_BUF_TESTS AND NOT PIGLIT_USE_GBM)
	message(FATAL_ERROR "PIGLIT_BUILD_DMA_BUF_TESTS require GBM")
endif()

if(PIGLIT_BUILD_EGL_TESTS AND NOT PIGLIT_USE_WAFFLE)
	message(FATAL_ERROR "Waffle has to be enabled for EGL tests to build")
endif()

if(PIGLIT_USE_X11)
	find_package(X11 REQUIRED)
	set(PIGLIT_HAS_X11 True)
	add_definitions(-DPIGLIT_HAS_X11)
endif()

if(PIGLIT_BUILD_GL_TESTS)
	find_package(OpenGL REQUIRED)
endif()

if(PIGLIT_USE_WAFFLE)
	if (NOT WIN32)
		pkg_check_modules(Waffle REQUIRED waffle-1)

		if(NOT Waffle_FOUND)
			message(FATAL_ERROR "Failed to find Waffle. If Waffle "
			"is not packaged for your distribution, you can get "
			"it at https://gitlab.freedesktop.org/mesa/waffle."
		)
		endif()

		# Check the installed waffle version.
		#
		# We cannot reliably check the version with pkg_check_modules(), but
		# instead must check the version manually as below. The problem is that,
		# if one passes a required version to pkg_check_modules(), CMake
		# validates the required version at most once for the lifetime of the
		# source tree.  If someone changes the required version by editing the
		# CMakeLists, CMake fails to detect the new requirement.
		set(Waffle_REQUIRED_VERSION "1.6.0")
		if(Waffle_VERSION VERSION_LESS Waffle_REQUIRED_VERSION)
			message(FATAL_ERROR "Found waffle-${Waffle_VERSION}, but "
			"piglit requires waffle-${Waffle_REQUIRED_VERSION}")
		endif()
	else ()
		find_path(Waffle_INCLUDE_DIRS waffle.h)
		find_library(Waffle_LDFLAGS waffle-1)
		if(Waffle_INCLUDE_DIRS AND Waffle_LDFLAGS)
			set(Waffle_FOUND TRUE)
		else()
			message(FATAL_ERROR "Failed to find Waffle. Get and build Waffle from "
				"https://gitlab.freedesktop.org/mesa/waffle and set "
				"Waffle_INCLUDE_DIRS and Waffle_LDFLAGS variables accordingly."
			)
		endif()
	endif ()

	add_definitions(-DPIGLIT_USE_WAFFLE)
	add_definitions(-DWAFFLE_API_VERSION=0x0103)
else()
	find_package(GLUT REQUIRED)
endif(PIGLIT_USE_WAFFLE)

if(PIGLIT_BUILD_GLES1_TESTS AND (NOT PIGLIT_USE_WAFFLE OR NOT PIGLIT_BUILD_EGL_TESTS))
	message(FATAL_ERROR "Option PIGLIT_BUILD_GLES1_TESTS requires EGL and PIGLIT_USE_WAFFLE")
endif()
if(PIGLIT_BUILD_GLES2_TESTS AND (NOT PIGLIT_USE_WAFFLE OR NOT PIGLIT_BUILD_EGL_TESTS))
	message(FATAL_ERROR "Option PIGLIT_BUILD_GLES2_TESTS requires EGL and PIGLIT_USE_WAFFLE")
endif()
if(PIGLIT_BUILD_GLES3_TESTS AND (NOT PIGLIT_USE_WAFFLE OR NOT PIGLIT_BUILD_EGL_TESTS))
	message(FATAL_ERROR "Option PIGLIT_BUILD_GLES3_TESTS requires EGL and PIGLIT_USE_WAFFLE")
endif()

if(PIGLIT_BUILD_CL_TESTS)
	find_package(OpenCL 1.2 REQUIRED)
endif(PIGLIT_BUILD_CL_TESTS)


if(PIGLIT_USE_GBM)
	pkg_check_modules(GBM REQUIRED gbm>=17.1)
	set(PIGLIT_HAS_GBM True)
	add_definitions(-DPIGLIT_HAS_GBM)
	set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${GBM_LIBRARIES})
	set(CMAKE_REQUIRED_LINK_OPTIONS ${GBM_LDFLAGS})
	include_directories(${GBM_INCLUDE_DIRS})

	CHECK_FUNCTION_EXISTS(gbm_bo_map PIGLIT_HAS_GBM_BO_MAP)
	if (PIGLIT_HAS_GBM_BO_MAP)
		add_definitions(-DPIGLIT_HAS_GBM_BO_MAP)
	endif()

	CHECK_FUNCTION_EXISTS(gbm_bo_get_fd_for_plane PIGLIT_HAS_GBM_BO_GET_FD_FOR_PLANE)
	if (PIGLIT_HAS_GBM_BO_GET_FD_FOR_PLANE)
		add_definitions(-DPIGLIT_HAS_GBM_BO_GET_FD_FOR_PLANE)
	endif()
endif()

if(PIGLIT_USE_WAYLAND)
	pkg_check_modules(WAYLAND REQUIRED wayland-client)
	set(PIGLIT_HAS_WAYLAND True)
	add_definitions(-DPIGLIT_HAS_WAYLAND)
	include_directories(${WAYLAND_INCLUDE_DIRS})

	FIND_LIBRARY(HAVE_XKBCOMMON NAMES xkbcommon)
	if(NOT HAVE_XKBCOMMON)
		message(FATAL_ERROR "Wayland support requires xkbcommon. "
			"Failed to find xkbcommon library.")
	endif()
	pkg_check_modules(XKBCOMMON QUIET xkbcommon)

	pkg_check_modules(WaylandProtocols REQUIRED wayland-protocols>=1.24)
	pkg_get_variable(WaylandProtocols_DATADIR wayland-protocols pkgdatadir)
	if (NOT WaylandProtocols_DATADIR)
		message(FATAL_ERROR "Failed to find wayland-protocols XML path")
	endif()

	pkg_check_modules(WaylandScanner REQUIRED wayland-scanner)
	pkg_get_variable(WaylandScannerPath wayland-scanner wayland_scanner)
	if (NOT WaylandScannerPath)
		message(FATAL_ERROR "Failed to find wayland-scanner path from pkg-config")
	endif()
	add_executable(WaylandScannerExe IMPORTED)
	set_property(TARGET WaylandScannerExe PROPERTY IMPORTED_LOCATION ${WaylandScannerPath})
endif()

if(PIGLIT_USE_X11 AND OPENGL_gl_LIBRARY AND PIGLIT_BUILD_GLX_TESTS)
	set(PIGLIT_HAS_GLX True)
	add_definitions(-DPIGLIT_HAS_GLX)
endif()

if(PIGLIT_BUILD_WGL_TESTS)
	set(PIGLIT_HAS_WGL True)
	add_definitions(-DPIGLIT_HAS_WGL)
endif()

IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
	pkg_check_modules(LIBDRM QUIET libdrm)
	pkg_check_modules(XCB QUIET xcb)
	pkg_check_modules(XCB_DRI2 QUIET xcb-dri2)
	pkg_check_modules(GLPROTO QUIET glproto)
	pkg_check_modules(LIBVULKAN QUIET vulkan)
ENDIF()

if(LIBDRM_FOUND)
	if(LIBDRM_VERSION VERSION_GREATER "2.4.109")
		set(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID true)
	else()
		set(PIGLIT_HAS_DRM_GET_DEVICE_BY_DEVID false)
	endif()
endif()

if(PIGLIT_BUILD_VK_TESTS)
	if (NOT LIBVULKAN_FOUND)
		message(FATAL_ERROR "libvulkan required by vulkan tests not found")
	endif()

	find_program(GLSLANG_VALIDATOR NAMES glslangValidator)

	if (NOT GLSLANG_VALIDATOR)
		message(FATAL_ERROR "glslangValidator required by vulkan tests not found")
	endif()
endif(PIGLIT_BUILD_VK_TESTS)

# Choose to build tests that use dma_buf.
#
# Piglit's dma_buf utilities require xcb-dri2 to gain DRM authentication, and
# gbm_bo_map() to be available for generating dma_bufs, and libdrm for fourcc
# definitions.
#
if(PIGLIT_BUILD_DMA_BUF_TESTS)
	if(PIGLIT_HAS_GBM_BO_MAP AND LIBDRM_FOUND AND LIBDRM_VERSION VERSION_GREATER "2.4.97" AND XCB_DRI2_FOUND)
		set(PIGLIT_BUILD_DMA_BUF_TESTS_IS_VALID true)
	else()
		message(FATAL_ERROR
			"PIGLIT_BUILD_DMA_BUF_TESTS require libdrm, "
			"gbm_bo_map(), libdrm>=2.4.98 and xcb-dri2")
		set(PIGLIT_BUILD_DMA_BUF_TESTS_IS_VALID false)
	endif()
endif()

IF(PIGLIT_BUILD_GLX_TESTS)
	pkg_check_modules(GLPROTO REQUIRED glproto)
ENDIF()

if (NOT Python_ADDITIONAL_VERSIONS)
	set(Python_ADDITIONAL_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6)
endif()
find_package(PythonInterp REQUIRED)
find_package(PythonNumpy 1.7.0 REQUIRED)
find_package(PythonMako 1.0.2 REQUIRED)

pkg_search_module(BASH_COMPLETION bash-completion)

# Default to compiling with debug information (`gcc -g`):
if(NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE Debug CACHE STRING
	"May be one of: None Debug RelWithDebInfo Release MinSizeRel" FORCE)
endif(NOT CMAKE_BUILD_TYPE)

if (NOT MSVC)
	if (PIGLIT_SSE2 AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)")
		# enables SSE2 and precision used on x86-64 by default
		SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2 -mfpmath=sse")
		SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2 -mfpmath=sse")
	else()
		# degrade performance a bit, but enforce required precision
		SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffloat-store")
		SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffloat-store")
	endif()
	CHECK_C_COMPILER_FLAG("-Wall" C_COMPILER_FLAG_WALL)
	IF (C_COMPILER_FLAG_WALL)
		SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
	ENDIF (C_COMPILER_FLAG_WALL)
	CHECK_CXX_COMPILER_FLAG("-Wall" CXX_COMPILER_FLAG_WALL)
	IF (CXX_COMPILER_FLAG_WALL)
		SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
	ENDIF (CXX_COMPILER_FLAG_WALL)

	# Target C99.  GCC's default is gnu11 for 5.0 and newer, gnu89 for
	# older versions.
	check_c_compiler_flag ("-std=gnu99" C_COMPILER_FLAG_STD_GNU99)
	if (C_COMPILER_FLAG_STD_GNU99)
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
	endif ()
	# MSVC does not support C99 variable length arrays
	CHECK_C_COMPILER_FLAG("-Werror=vla" C_COMPILER_FLAG_WEVLA)
	IF (C_COMPILER_FLAG_WEVLA)
		SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=vla")
	ENDIF ()
	# GCC allows void pointer arithmetic, but it is not part of ISO C and
	# in particular MSVC will throw `C2036: 'void *' : unknown size`
	check_c_compiler_flag ("-Werror=pointer-arith" C_COMPILER_FLAG_WEPOINTER_ARITH)
	if (C_COMPILER_FLAG_WEPOINTER_ARITH)
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=pointer-arith")
	endif ()
	# MSVC only supports C99 variadic macros.  It doesn't support the
	# non-standard GNU named variadic macro syntax that's documented in
	# https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
	#
	# XXX: on older GCC version this option has no effect unless -Wpedantic
	# is set, but this should be fixed on future GCC versions, per
	# https://gcc.gnu.org/ml/gcc-patches/2014-04/msg01459.html
	check_c_compiler_flag ("-Werror=variadic-macros" C_COMPILER_FLAG_WVARIADIC_MACROS)
	if (C_COMPILER_FLAG_WVARIADIC_MACROS)
		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=variadic-macros")
	endif ()

	CHECK_CXX_COMPILER_FLAG("-Wno-narrowing" CXX_COMPILER_FLAG_WNO_NARROWING)
	IF (CXX_COMPILER_FLAG_WNO_NARROWING)
		SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing")
	ENDIF (CXX_COMPILER_FLAG_WNO_NARROWING)
else ()
	# Adjust warnings
	add_definitions (-W3)
	add_definitions (-wd4018) # signed/unsigned mismatch
	add_definitions (-wd4244) # conversion from 'type1' to 'type2', possible loss of data
	add_definitions (-wd4305) # truncation from 'type1' to 'type2'
	add_definitions (-wd4800) # forcing value to bool 'true' or 'false' (performance warning)

	add_definitions (-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
	add_definitions (-D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
endif ()

if (MINGW)
	# Match MSVC default stack size
	set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,1048576")
endif ()

if (${CMAKE_C_COMPILER_ID} STREQUAL "SunPro")
	# Use C++ to link C files.
	# http://developers.sun.com/solaris/articles/mixing.html#linking
	# Modified rule from Modules/CMakeCInformation.cmake.
	set (CMAKE_C_LINK_EXECUTABLE
		"<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()

# Always enable GNU C extensions.  Non-GNU platforms will need to
# define wrappers for them.
add_definitions(-D_GNU_SOURCE)

if (WIN32)
	# MSVC & MinGW only define & use APIENTRY
	add_definitions (-DGLAPIENTRY=__stdcall)

	# Avoid namespace pollution when including windows.h
	# http://support.microsoft.com/kb/166474
	add_definitions (-DWIN32_LEAN_AND_MEAN=1)

	# Don't define min/max macros
	add_definitions (-DNOMINMAX)

	# Even more no min/max macros
	add_definitions (-D_CRT_DECLARE_NONSTDC_NAMES=0)

	# Define M_PI and others
	add_definitions (-D_USE_MATH_DEFINES)
endif (WIN32)

if (APPLE)
	# Don't warn about using deprecated OpenGL/GLUT functions.
	# TODO: It would be nice to silence just the deprecation macros from
	# OpenGLAvailability.h as opposed to all deprecated functions.
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
endif ()

if (PIGLIT_BUILD_GL_TESTS)
	if (APPLE)
		find_path(GLEXT_INCLUDE_DIR
			NAMES OpenGL/glext.h
			PATHS ${OPENGL_INCLUDE_DIR}
			DOC "Include for OpenGL/glext.h on OSX"
		)
	else()
		find_path(GLEXT_INCLUDE_DIR
			NAMES GL/glext.h
			PATHS ${OPENGL_INCLUDE_DIR}
			DOC "Include for GL/glext.h"
		)
	endif()
endif()

if(CMAKE_USE_PTHREADS_INIT)
	set(PIGLIT_HAS_PTHREADS true)
	add_definitions(-DPIGLIT_HAS_PTHREADS)
endif()

FIND_LIBRARY(HAVE_LIBRT NAMES rt)
if(HAVE_LIBRT)
	set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif()

check_c_source_compiles(
	"
	#define _POSIX_C_SOURCE 199309L
	#include <time.h>
	int main() { return clock_gettime(CLOCK_MONOTONIC, NULL); }
	"
	PIGLIT_HAS_POSIX_CLOCK_MONOTONIC
)

if(PIGLIT_HAS_PTHREADS AND PIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
	check_c_source_compiles(
		"
		#include <signal.h>
		#include <time.h>
		static void timeout(union sigval val) { }
		int main() {
			struct sigevent sev = {
				.sigev_notify = SIGEV_THREAD,
				.sigev_notify_function = timeout,
			};
			timer_t timerid;
			return timer_create(CLOCK_MONOTONIC, &sev, &timerid);
		}
		"
		PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD
	)
endif()

set(CMAKE_REQUIRED_LIBRARIES)

if(PIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
	add_definitions(-DPIGLIT_HAS_POSIX_CLOCK_MONOTONIC)
endif()

if(PIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD)
	add_definitions(-DPIGLIT_HAS_POSIX_TIMER_NOTIFY_THREAD)
endif()

if(GBM_FOUND)
	FIND_LIBRARY(HAVE_LIBCACA NAMES caca)
	if(HAVE_LIBCACA)
		set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} caca)
		add_definitions(-DPIGLIT_HAS_LIBCACA)
	endif(HAVE_LIBCACA)
endif(GBM_FOUND)

if(PIGLIT_BUILD_EGL_TESTS)
	pkg_check_modules(EGL REQUIRED egl)
	set(PIGLIT_HAS_EGL True)
	add_definitions(-DPIGLIT_HAS_EGL)
	include_directories(${EGL_INCLUDE_DIRS})
	add_definitions (${EGL_CFLAGS_OTHER})
endif()

# Put all executables into the bin subdirectory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${piglit_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${piglit_BINARY_DIR}/lib)

# Do the same for MSVC, regardless of the build type. This only works correctly
# for CMake 2.8.1 and above.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${piglit_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${piglit_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${piglit_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${piglit_BINARY_DIR}/bin)

check_function_exists(asprintf  HAVE_ASPRINTF)
check_function_exists(ffs       HAVE_FFS)
check_function_exists(strchrnul HAVE_STRCHRNUL)
check_function_exists(strndup   HAVE_STRNDUP)
if(NOT MINGW)
	check_function_exists(fopen_s   HAVE_FOPEN_S)
endif()
check_function_exists(setrlimit HAVE_SETRLIMIT)

check_symbol_exists(htobe32 "endian.h" HAVE_HTOBE32)
check_symbol_exists(htole16 "endian.h" HAVE_HTOLE16)
check_symbol_exists(htole32 "endian.h" HAVE_HTOLE32)
check_symbol_exists(htole64 "endian.h" HAVE_HTOLE64)

check_include_file(sys/time.h  HAVE_SYS_TIME_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(sys/resource.h  HAVE_SYS_RESOURCE_H)
check_include_file(sys/stat.h  HAVE_SYS_STAT_H)
check_include_file(unistd.h    HAVE_UNISTD_H)
check_include_file(fcntl.h     HAVE_FCNTL_H)
check_include_file(linux/sync_file.h HAVE_LINUX_SYNC_FILE_H)
check_include_file(endian.h    HAVE_ENDIAN_H)
check_include_file(libgen.h    HAVE_LIBGEN_H)

if(DEFINED PIGLIT_INSTALL_VERSION)
	set(PIGLIT_INSTALL_VERSION_SUFFIX
	    "-${PIGLIT_INSTALL_VERSION}")
else()
	set(PIGLIT_INSTALL_VERSION_SUFFIX "")
endif()
set(PIGLIT_INSTALL_LIBDIR
    "${CMAKE_INSTALL_LIBDIR}/piglit${PIGLIT_INSTALL_VERSION_SUFFIX}")
if(NOT IS_ABSOLUTE ${PIGLIT_INSTALL_LIBDIR})
	set(PIGLIT_INSTALL_FULL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${PIGLIT_INSTALL_LIBDIR}")
else()
	set(PIGLIT_INSTALL_FULL_LIBDIR "${PIGLIT_INSTALL_LIBDIR}")
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--enable-new-dtags")
endif(CMAKE_SYSTEM_NAME STREQUAL "Linux")

SET(CMAKE_INSTALL_RPATH "${PIGLIT_INSTALL_FULL_LIBDIR}/lib")

configure_file(
	"${piglit_SOURCE_DIR}/tests/util/config.h.in"
	"${piglit_BINARY_DIR}/tests/util/config.h"
)

include(cmake/piglit_util.cmake)
include(cmake/piglit_dispatch.cmake)

include_directories(src)
add_subdirectory(cmake/target_api)
add_subdirectory(generated_tests)
add_subdirectory(replayer)


##############################################################################
# Packaging

install (
	FILES
		COPYING
		README.md
		RELEASE
	DESTINATION share/doc/piglit${PIGLIT_INSTALL_VERSION_SUFFIX}
)

install (
	DIRECTORY framework
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
	FILES_MATCHING PATTERN "*.py"
)

install (
	DIRECTORY templates
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
)

install (
	DIRECTORY tests
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
	FILES_MATCHING REGEX ".*\\.(xml|xml.gz|py|program_test|shader_test|shader_source|frag|vert|geom|tesc|tese|comp|spv|ktx|cl|txt|inc|vk_shader_test)$"
	REGEX "CMakeFiles|CMakeLists|serializer.py|opengl.py|cl.py|quick_gl.py|glslparser.py|shader.py|quick_shader.py|no_error.py|llvmpipe_gl.py|sanity.py" EXCLUDE
)

install (
	DIRECTORY ${CMAKE_BINARY_DIR}/tests
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
	FILES_MATCHING REGEX ".*\\.xml.gz"
)

install (
	DIRECTORY ${CMAKE_BINARY_DIR}/generated_tests
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
	FILES_MATCHING REGEX ".*\\.(shader_test|program_test|frag|vert|geom|tesc|tese|comp|cl|txt|vk_shader_test)$"
	REGEX "CMakeFiles|CMakeLists" EXCLUDE
)

install (
	DIRECTORY generated_tests
	DESTINATION ${PIGLIT_INSTALL_LIBDIR}
	FILES_MATCHING REGEX ".*\\.inc$"
	REGEX "CMakeFiles|CMakeLists" EXCLUDE
)

if (BASH_COMPLETION_FOUND)
	pkg_get_variable(BASH_COMPLETION_COMPLETIONSDIR bash-completion completionsdir)

	if(NOT "${BASH_COMPLETION_PREFIX}" STREQUAL "${CMAKE_INSTALL_PREFIX}")
		string(REGEX REPLACE "^${BASH_COMPLETION_PREFIX}" "${CMAKE_INSTALL_PREFIX}" COMP_DIR ${BASH_COMPLETION_COMPLETIONSDIR})
		set(BASH_COMPLETION_COMPLETIONSDIR ${COMP_DIR})
		unset(COMP_DIR)
	endif()

	install(
		FILES completions/bash/piglit
		DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR}
	)
endif (BASH_COMPLETION_FOUND)

if (WIN32)
	set (PYTHON_SUFFIX ".py")
else ()
	set (PYTHON_SUFFIX "")
endif ()
install (
	PROGRAMS piglit RENAME piglit${PIGLIT_INSTALL_VERSION_SUFFIX}${PYTHON_SUFFIX}
	DESTINATION ${CMAKE_INSTALL_BINDIR}
)

# Install MinGW runtime DLLs
if (MINGW)
	if (CMAKE_SIZEOF_VOID_P EQUAL 8)
		set (LIBGCC_DLL_NAME libgcc_s_seh-1.dll)
	else ()
		set (LIBGCC_DLL_NAME libgcc_s_sjlj-1.dll)
	endif ()
	execute_process (
		COMMAND ${CMAKE_C_COMPILER} -print-file-name=${LIBGCC_DLL_NAME}
		OUTPUT_STRIP_TRAILING_WHITESPACE
		OUTPUT_VARIABLE LIBGCC_DLL
	)
	execute_process (
		COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libstdc++-6.dll
		OUTPUT_STRIP_TRAILING_WHITESPACE
		OUTPUT_VARIABLE LIBSTDCXX_DLL
	)
	if (EXISTS ${LIBGCC_DLL})
		message (STATUS "Found libgcc DLL: ${LIBGCC_DLL}")
		install (FILES ${LIBGCC_DLL} DESTINATION ${PIGLIT_INSTALL_LIBDIR}/bin)
	endif ()
	if (EXISTS ${LIBSTDCXX_DLL})
		message (STATUS "Found libstdc++ DLL: ${LIBSTDCXX_DLL}")
		install (FILES ${LIBSTDCXX_DLL} DESTINATION ${PIGLIT_INSTALL_LIBDIR}/bin)
	endif ()
endif ()

# Install Waffle DLL if specified
if (WIN32 AND Waffle_DLL)
	install (FILES ${Waffle_DLL} DESTINATION ${PIGLIT_INSTALL_LIBDIR}/bin)
endif ()


set (CPACK_PACKAGE_VERSION_MAJOR "1")
set (CPACK_PACKAGE_VERSION_MINOR "0")

# Use current date in YYYYMMDD format as patch number
execute_process (
	COMMAND ${PYTHON_EXECUTABLE} -c "import time, sys; sys.stdout.write(time.strftime('%Y%m%d'))"
	OUTPUT_VARIABLE CPACK_PACKAGE_VERSION_PATCH
)

# cpack mistakenly detects Mingw-w64 as win32
if (MINGW)
	if (CMAKE_SIZEOF_VOID_P EQUAL 8)
		set (CPACK_SYSTEM_NAME win64)
	endif ()
endif ()

# See http://www.vtk.org/Wiki/CMake:CPackPackageGenerators
if (WIN32)
	set (CPACK_GENERATOR "7Z")
	set (CPACK_STRIP_FILES ON)
else ()
	set (CPACK_GENERATOR "TBZ2")
endif ()

include(CPack)
