PROJECT(extlib)

# Set common properties for extlib targets.
INCLUDE(SetMSVCDebugPath)
FUNCTION(SET_EXTLIB_PROPERTIES)
	FOREACH(_target ${ARGV})
		IF(TARGET ${_target})
			# Exclude from ALL builds.
			SET_TARGET_PROPERTIES(${_target} PROPERTIES EXCLUDE_FROM_ALL TRUE)
		ENDIF(TARGET ${_target})
	ENDFOREACH(_target ${ARGV})
ENDFUNCTION(SET_EXTLIB_PROPERTIES)

# zlib: Assembly optimizations.
# TODO: Test on all archs and fix Z_PREFIX issues.
# TODO: Add more assembly files from contrib/ besides the
# default ones that were listed in zlib's CMakeLists.txt.
IF(CPU_i386 OR CPU_amd64)
	# i386/amd64. Check sizeof(void*) for the actual architecture,
	# since building 32-bit on 64-bit isn't considered "cross-compiling",
	# so CMAKE_SYSTEM_PROCESSOR might not be accurate.
	# NOTE: Checking CMAKE_CL_64 instead of sizeof(void*) for MSVC builds.
	IF(MSVC AND CMAKE_CL_64)
		SET(AMD64 "ON")
	ELSEIF(NOT MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
		SET(AMD64 "ON")
	ELSE()
		SET(ASM686 "ON")
	ENDIF()
ENDIF(CPU_i386 OR CPU_amd64)

# Don't install any of these libraries by default.
# zlib-ng and libpng will be installed if they're
# built as shared libraries.
SET(SKIP_INSTALL_LIBRARIES ON)
SET(SKIP_INSTALL_HEADERS ON)
SET(SKIP_INSTALL_FILES ON)
SET(SKIP_INSTALL_ALL ON)
SET(BUILD_SHARED_LIBS OFF)

INCLUDE(DirInstallPaths)
SET(INSTALL_BIN_DIR "${DIR_INSTALL_DLL}")
SET(INSTALL_LIB_DIR "${DIR_INSTALL_LIB}")

IF(USE_INTERNAL_ZLIB)
	# Use the internal copy of zlib-ng.
	# On Windows and Mac OS X, this will build DLLs.
	# On other systems, this will be statically-linked.
	IF(WIN32 OR APPLE)
		SET(SKIP_INSTALL_LIBRARIES OFF)
		SET(SKIP_INSTALL_ALL OFF)
		SET(BUILD_SHARED_LIBS ON)
		SET(BUILD_STATIC_LIBS OFF)
	ELSE()
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS OFF)
		SET(BUILD_STATIC_LIBS ON)
	ENDIF()

	# zlib-ng options
	SET(WITH_GZFILEOP ON)
	SET(ZLIB_COMPAT ON)
	SET(ZLIB_ENABLE_TESTS OFF)
	SET(ZLIBNG_ENABLE_TESTS OFF)
	SET(WITH_GTEST OFF)
	SET(WITH_FUZZERS OFF)
	SET(WITH_BENCHMARKS OFF)
	SET(WITH_BENCHMARK_APPS OFF)
	SET(WITH_OPTIM ON)
	SET(WITH_REDUCED_MEM OFF)
	SET(WITH_NEW_STRATEGIES ON)
	SET(WITH_NATIVE_INSTRUCTIONS OFF)
	SET(WITH_MAINTAINER_WARNINGS OFF)
	SET(WITH_CODE_COVERAGE OFF)
	SET(WITH_INFLATE_STRICT OFF)
	SET(WITH_INFLATE_ALLOW_INVALID_DIST OFF)
	SET(WITH_UNALIGNED ON)

	# CPU-specific optimizations
	SET(WITH_ACLE ON)
	SET(WITH_NEON ON)
	SET(WITH_ALTIVEC ON)
	SET(WITH_POWER8 ON)
	SET(WITH_POWER9 ON)
	SET(WITH_RVV ON)
	SET(WITH_DFLTCC_DEFLATE OFF)
	SET(WITH_DFLTCC_INFLATE OFF)
	SET(WITH_CRC32_VX ON)
	SET(WITH_AVX2 ON)
	SET(WITH_AVX512 ON)
	SET(WITH_AVX512VNNI ON)
	SET(WITH_SSE2 ON)
	SET(WITH_SSSE3 ON)
	SET(WITH_SSE42 ON)
	SET(WITH_PCLMULQDQ ON)
	SET(WITH_VPCLMULQDQ ON)

	SET(INSTALL_UTILS OFF)

	ADD_SUBDIRECTORY(zlib-ng)
	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	#SET_EXTLIB_PROPERTIES(zlib)
	SET_EXTLIB_PROPERTIES(zlibstatic)
ENDIF(USE_INTERNAL_ZLIB)

IF(USE_INTERNAL_PNG)
	IF(USE_INTERNAL_ZLIB)
		# Using internal ZLIB.
		# Don't search for ZLIB using FIND_PACKAGE().
		SET(PNG_BUILD_ZLIB ON)
	ENDIF(USE_INTERNAL_ZLIB)

	# Use the internal copy of libpng.
	# On Windows and Mac OS X, this will build DLLs.
	# On other systems, this will be statically-linked.
	IF(WIN32 OR APPLE)
		SET(PNG_SHARED ON)
		SET(PNG_STATIC OFF)
		SET(SKIP_INSTALL_LIBRARIES OFF)
		SET(SKIP_INSTALL_ALL OFF)
		SET(BUILD_SHARED_LIBS ON)
		SET(BUILD_STATIC_LIBS OFF)
	ELSE()
		SET(PNG_SHARED OFF)
		SET(PNG_STATIC ON)
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS OFF)
		SET(BUILD_STATIC_LIBS ON)
	ENDIF()

	SET(PNG_TESTS OFF)
	SET(PNG_TOOLS OFF)
	SET(PNG_DEBUG OFF)
	SET(PNG_HARDWARE_OPTIMIZATIONS ON)

	ADD_SUBDIRECTORY(libpng)
	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	#SET_EXTLIB_PROPERTIES(png_shared)
	SET_EXTLIB_PROPERTIES(png_static)
ENDIF(USE_INTERNAL_PNG)

IF(USE_INTERNAL_ZSTD)
	# Use the internal copy of zstd.
	# On Windows and Mac OS X, this will build DLLs.
	# On other systems, this will be statically-linked.
	IF(WIN32 OR APPLE)
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL OFF)
		SET(BUILD_SHARED_LIBS ON)
		SET(BUILD_STATIC_LIBS OFF)
		SET(ZSTD_LIBRARY zstd)
	ELSE()
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS OFF)
		SET(BUILD_STATIC_LIBS ON)
		SET(ZSTD_LIBRARY zstdstatic)
	ENDIF()
	SET(ZSTD_LIBRARIES "${ZSTD_LIBRARY}")

	ADD_SUBDIRECTORY(zstd)
	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	#SET_EXTLIB_PROPERTIES(zstd)
	SET_EXTLIB_PROPERTIES(zstdstatic)
ELSE(USE_INTERNAL_ZSTD)
	SET(ZSTD_LIBRARY zstd)
ENDIF(USE_INTERNAL_ZSTD)

# minizip-ng
SET(SKIP_INSTALL_LIBRARIES ON)
SET(SKIP_INSTALL_ALL ON)
SET(BUILD_SHARED_LIBS OFF)
SET(BUILD_STATIC_LIBS ON)
SET(MZ_COMPAT ON)
SET(MZ_ZLIB ON)
SET(MZ_BZIP2 OFF)
SET(MZ_LZMA OFF)
SET(MZ_ZSTD ${ENABLE_ZSTD})
SET(MZ_FETCH_LIBS OFF)
SET(MZ_FORCE_FETCH_LIBS OFF)
SET(MZ_PKCRYPT OFF)
SET(MZ_WZAES OFF)
SET(MZ_LIBCOMP OFF)
SET(MZ_LIBBSD OFF)
SET(MZ_OPENSSL OFF)
SET(MZ_BRG OFF)
SET(MZ_ICONV OFF)
SET(MZ_SIGNING OFF)
SET(MZ_COMPRESS_ONLY OFF)
SET(MZ_DECOMPRESS_ONLY OFF)
SET(MZ_BUILD_TESTS ON)	# Allow manually building test executables.
SET(MZ_BUILD_UNIT_TESTS OFF)
SET(MZ_BUILD_FUZZ_TESTS OFF)
SET(MZ_CODE_COVERAGE OFF)
SET(MZ_FILE32_API OFF)
ADD_SUBDIRECTORY(minizip-ng)
SET_EXTLIB_PROPERTIES(minizip)
SET_EXTLIB_PROPERTIES(minigzip_cmd)
SET_EXTLIB_PROPERTIES(minizip_cmd)
SET_EXTLIB_PROPERTIES(test_cmd)
TARGET_COMPILE_DEFINITIONS(minizip PUBLIC -DMZ_COMPAT_VERSION=120)
UNSET(USE_COMPAT)
UNSET(COMPRESS_ONLY)
UNSET(DECOMPRESS_ONLY)

# inih
SET(SKIP_INSTALL_LIBRARIES ON)
SET(SKIP_INSTALL_ALL ON)
SET(BUILD_SHARED_LIBS OFF)
SET(BUILD_STATIC_LIBS ON)
ADD_SUBDIRECTORY(inih)
SET_EXTLIB_PROPERTIES(inih)

# TinyXML2
IF(USE_INTERNAL_XML)
	# Use the internal copy of TinyXML2.
	# On Windows, this will build DLLs.
	# On other systems, this will be statically-linked.
	# TODO: Build a dylib for Mac OS X.
	IF(WIN32)
		SET(SKIP_INSTALL_LIBRARIES OFF)
		SET(SKIP_INSTALL_ALL OFF)
		SET(BUILD_STATIC_LIBS OFF)
		SET(BUILD_SHARED_LIBS ON)
	ELSE()
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_STATIC_LIBS ON)
		SET(BUILD_SHARED_LIBS OFF)
	ENDIF()

	# Build TinyXML2.
	ADD_SUBDIRECTORY(tinyxml2)

	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	SET_EXTLIB_PROPERTIES(tinyxml2_static)
	#SET_EXTLIB_PROPERTIES(tinyxml2)

	# TODO: Set TinyXML2::tinyxml2 and use it in libromdata?
ENDIF(USE_INTERNAL_XML)

# UnICE68 for Atari ST SNDH files.
IF(ENABLE_UNICE68)
	SET(BUILD_UNICE68_CLI ON) # only builds if unice68_exe is explicitly built
	SET(BUILD_STATIC_LIBS ON)
	SET(BUILD_SHARED_LIBS OFF)
	ADD_SUBDIRECTORY(unice68)
	SET_EXTLIB_PROPERTIES(unice68_lib)
	SET_EXTLIB_PROPERTIES(unice68_exe)
ENDIF(ENABLE_UNICE68)

# libmspack-xenia for LZX-compressed Xbox 360 executables.
IF(ENABLE_LIBMSPACK)
	SET(BUILD_STATIC_LIBS ON)
	SET(BUILD_SHARED_LIBS OFF)
	ADD_SUBDIRECTORY(libmspack-xenia)
	SET_EXTLIB_PROPERTIES(libmspack)
ENDIF(ENABLE_LIBMSPACK)

# PowerVR texture decompression.
IF(ENABLE_PVRTC)
	SET(BUILD_STATIC_LIBS ON)
	SET(BUILD_SHARED_LIBS OFF)
	ADD_SUBDIRECTORY(PowerVR)
	SET_EXTLIB_PROPERTIES(pvrtc)
ENDIF(ENABLE_PVRTC)

IF(USE_INTERNAL_LZ4)
	# Use the internal copy of LZ4.
	# On Windows and Mac OS X, this will build DLLs.
	# On other systems, this will be statically-linked.
	IF(WIN32 OR APPLE)
		SET(SKIP_INSTALL_LIBRARIES OFF)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS ON)
		SET(BUILD_STATIC_LIBS OFF)
	ELSE()
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS OFF)
		SET(BUILD_STATIC_LIBS ON)
	ENDIF()
	SET(LZ4_BUNDLED_MODE ON)
	ADD_SUBDIRECTORY(lz4/build/cmake)
	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	#SET_EXTLIB_PROPERTIES(lz4_shared)
	SET_EXTLIB_PROPERTIES(lz4_static)
	# lz4 programs that we don't need.
	SET_EXTLIB_PROPERTIES(lz4cli lz4c)
ENDIF(USE_INTERNAL_LZ4)

IF(USE_INTERNAL_LZO)
	# Use the internal copy of LZO. (actually MiniLZO)
	# On Windows and Mac OS X, this will build DLLs.
	# On other systems, this will be statically-linked.
	IF(WIN32 OR APPLE)
		SET(SKIP_INSTALL_LIBRARIES OFF)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS ON)
		SET(BUILD_STATIC_LIBS OFF)
	ELSE()
		SET(SKIP_INSTALL_LIBRARIES ON)
		SET(SKIP_INSTALL_ALL ON)
		SET(BUILD_SHARED_LIBS OFF)
		SET(BUILD_STATIC_LIBS ON)
	ENDIF()
	ADD_SUBDIRECTORY(minilzo)
	# NOTE: Cannot remove targets from all builds
	# if they're being installed.
	#SET_EXTLIB_PROPERTIES(minilzo)
ENDIF(USE_INTERNAL_LZO)

# rapidjson
SET(RAPIDJSON_BUILD_DOC OFF)
SET(RAPIDJSON_BUILD_EXAMPLES OFF)
SET(RAPIDJSON_BUILD_TESTS OFF)
SET(RAPIDJSON_BUILD_THIRDPARTY_GTEST OFF)
SET(RAPIDJSON_BUILD_CXX11 ON)
SET(RAPIDJSON_BUILD_ASAN OFF)
SET(RAPIDJSON_BUILD_UBSAN OFF)
SET(RAPIDJSON_HAS_STDSTRING ON)
ADD_SUBDIRECTORY(rapidjson)
SET(RAPIDJSON_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/include" PARENT_SCOPE)

# Google Test
IF(BUILD_TESTING)
	# Reference: http://stackoverflow.com/questions/12540970/how-to-make-gtest-build-mdd-instead-of-mtd-by-default-using-cmake
	SET(gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll")
	SET(SKIP_INSTALL_LIBRARIES ON)
	SET(SKIP_INSTALL_ALL ON)

	# Use shared libraries on Windows.
	IF(WIN32)
		SET(BUILD_STATIC_LIBS OFF)
		SET(BUILD_SHARED_LIBS ON)
	ELSE(WIN32)
		SET(BUILD_STATIC_LIBS ON)
		SET(BUILD_SHARED_LIBS OFF)
	ENDIF(WIN32)

	ADD_SUBDIRECTORY(googletest)
	INCLUDE(SetMSVCDebugPath)
	SET_EXTLIB_PROPERTIES(
		gtest gtest_main gtest_no_exception gtest_main_no_exception
		gtest_main_no_rtti gtest_dll gtest_main_use_own_tuple
		gmock gmock_main gmock_main_no_exception
		gmock_main_no_rtti gmock_main_use_own_tuple
		)
	IF(WIN32)
		# GTest is a DLL, so we need to set this.
		TARGET_COMPILE_DEFINITIONS(gtest INTERFACE GTEST_LINKED_AS_SHARED_LIBRARY=1)
		TARGET_COMPILE_DEFINITIONS(gtest_main INTERFACE GTEST_LINKED_AS_SHARED_LIBRARY=1)
	ENDIF(WIN32)
ENDIF(BUILD_TESTING)

# Basis Universal ASTC decoder
IF(ENABLE_ASTC)
	ADD_SUBDIRECTORY(basisu_astc)
	SET_EXTLIB_PROPERTIES(basisu_astc)
ENDIF(ENABLE_ASTC)

# uniwidth (subset of gnulib) (needed for wcwidth())
# wcwidth() requires _XOPEN_SOURCE.
SET(OLD_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
SET(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_XOPEN_SOURCE)
CHECK_SYMBOL_EXISTS(wcwidth "wchar.h" HAVE_WCWIDTH)
SET(CMAKE_REQUIRED_DEFINITIONS ${OLD_CMAKE_REQUIRED_DEFINITIONS})
UNSET(OLD_CMAKE_REQUIRED_DEFINITIONS)
IF(NOT HAVE_WCWIDTH)
	ADD_SUBDIRECTORY(uniwidth)
	SET_EXTLIB_PROPERTIES(uniwidth)
ENDIF(NOT HAVE_WCWIDTH)

# MicroTAR (for libromdata tests)
ADD_SUBDIRECTORY(microtar)
SET_EXTLIB_PROPERTIES(microtar)
