view CMakeLists.txt @ 25:92156fe32755

impl/ppc/altivec: update to new implementation the signed average function is wrong; it needs to round up the number when only one of them is odd, but that doesn't necessarily seem to be true because altivec is weird, and that's what we need to emulate the quirks for. ugh. also the altivec backend uses the generic functions instead of fallbacks because it does indeed use the exact same memory structure as the generic implementation...
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 11:15:59 +0000
parents e26874655738
children d00b95f95dd1
line wrap: on
line source

cmake_minimum_required(VERSION 3.23)

project(vec VERSION 3.0.0 DESCRIPTION "a tiny C99 SIMD vector library" LANGUAGES C)

add_library(vec SHARED "src/vec.c;src/cpu.c;src/impl/generic.c;src/impl/fallback.c")

include(CheckCCompilerFlag)

if(MSVC)
	# Untested!

	if(CMAKE_SIZEOF_VOID_P EQUAL 8)
		set(COMPILER_HAS_MMX OFF)
	else()
		set(COMPILER_HAS_MMX ON)
		set(COMPILER_MMX_FLAGS "") # none?
	endif()
	check_c_compiler_flag("/arch:SSE2" COMPILER_HAS_SSE2)
	if(COMPILER_HAS_SSE2)
		set(COMPILER_SSE2_FLAGS "/arch:SSE2")
	endif()
	check_c_compiler_flag("/arch:SSE4.2" COMPILER_HAS_SSE41)
	if(COMPILER_HAS_SSE41)
		set(COMPILER_SSE41_FLAGS "/arch:SSE4.2")
	endif()
	check_c_compiler_flag("/arch:AVX2" COMPILER_HAS_AVX2)
	if(COMPILER_HAS_AVX2)
		set(COMPILER_AVX2_FLAGS "/arch:AVX2")
	endif()
	check_c_compiler_flag("/arch:AVX512" COMPILER_HAS_AVX512F)
	if(COMPILER_HAS_AVX512F)
		set(COMPILER_AVX512F_FLAGS "/arch:AVX512")
	endif()
	# TODO we have to try_compile to detect NEON
else()
	check_c_compiler_flag("-maltivec" COMPILER_HAS_ALTIVEC)
	if(COMPILER_HAS_ALTIVEC)
		set(COMPILER_ALTIVEC_FLAGS "-maltivec")
	endif()
	#check_c_compiler_flag("-mfpu=neon" COMPILER_HAS_NEON)
	#if(COMPILER_HAS_NEON)
	#	set(COMPILER_NEON_FLAGS "-mfpu=neon")
	#endif()
	check_c_compiler_flag("-mmmx" COMPILER_HAS_MMX)
	if(COMPILER_HAS_MMX)
		set(COMPILER_MMX_FLAGS "-mmmx")
	endif()
	check_c_compiler_flag("-msse2" COMPILER_HAS_SSE2)
	if(COMPILER_HAS_SSE2)
		set(COMPILER_SSE2_FLAGS "-msse2")
	endif()
	check_c_compiler_flag("-msse4.1" COMPILER_HAS_SSE41)
	if(COMPILER_HAS_SSE41)
		set(COMPILER_SSE41_FLAGS "-msse4.1")
	endif()
	check_c_compiler_flag("-mavx2" COMPILER_HAS_AVX2)
	if(COMPILER_HAS_AVX2)
		set(COMPILER_AVX2_FLAGS "-mavx2")
	endif()
	check_c_compiler_flag("-mavx512f" COMPILER_HAS_AVX512F)
	if(COMPILER_HAS_AVX512F)
		set(COMPILER_AVX512F_FLAGS "-mavx512f")
	endif()
endif()

if(COMPILER_HAS_ALTIVEC)
	target_sources(vec PRIVATE "src/impl/ppc/altivec.c")
	set_source_files_properties("src/impl/ppc/altivec.c" PROPERTIES COMPILE_FLAGS "${COMPILER_ALTIVEC_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_ALTIVEC")
endif()

if(COMPILER_HAS_NEON)
	target_sources(vec PRIVATE "src/impl/arm/neon.c")
	set_source_files_properties("src/impl/arm/neon.c" PROPERTIES COMPILE_FLAGS "${COMPILER_NEON_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_NEON")
endif()

if(COMPILER_HAS_MMX)
	target_sources(vec PRIVATE "src/impl/x86/mmx.c")
	set_source_files_properties("src/impl/x86/mmx.c" PROPERTIES COMPILE_FLAGS "${COMPILER_MMX_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_MMX")
endif()

if(COMPILER_HAS_SSE2)
	target_sources(vec PRIVATE "src/impl/x86/sse2.c")
	set_source_files_properties("src/impl/x86/sse2.c" PROPERTIES COMPILE_FLAGS "${COMPILER_SSE2_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_SSE2")
endif()

if(COMPILER_HAS_SSE41)
	target_sources(vec PRIVATE "src/impl/x86/sse41.c")
	set_source_files_properties("src/impl/x86/sse41.c" PROPERTIES COMPILE_FLAGS "${COMPILER_SSE41_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_SSE41")
endif()

if(COMPILER_HAS_AVX2)
	target_sources(vec PRIVATE "src/impl/x86/avx2.c")
	set_source_files_properties("src/impl/x86/avx2.c" PROPERTIES COMPILE_FLAGS "${COMPILER_AVX2_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_AVX2")
endif()

if(COMPILER_HAS_AVX512F)
	target_sources(vec PRIVATE "src/impl/x86/avx512f.c")
	set_source_files_properties("src/impl/x86/avx512f.c" PROPERTIES COMPILE_FLAGS "${COMPILER_AVX512F_FLAGS}")
	target_compile_definitions(vec PRIVATE "-DVEC_COMPILER_HAS_AVX512F")
endif()


#########################################################################
# integer types; it's nice to accommodate for older broken systems that
# may not have stdint.h.

include(CheckTypeSize)

check_type_size("int16_t"   INT16_T_SIZE   LANGUAGE C)
check_type_size("uint16_t"  UINT16_T_SIZE  LANGUAGE C)
check_type_size("u_int16_t" U_INT16_T_SIZE LANGUAGE C)
check_type_size("int32_t"   INT32_T_SIZE   LANGUAGE C)
check_type_size("uint32_t"  UINT32_T_SIZE  LANGUAGE C)
check_type_size("u_int32_t" U_INT32_T_SIZE LANGUAGE C)
check_type_size("int64_t"   INT64_T_SIZE   LANGUAGE C)
check_type_size("uint64_t"  UINT64_T_SIZE  LANGUAGE C)
check_type_size("u_int64_t" U_INT64_T_SIZE LANGUAGE C)
check_type_size("short"     SHORT_SIZE     LANGUAGE C)
check_type_size("int"       INT_SIZE       LANGUAGE C)
check_type_size("long"      LONG_SIZE      LANGUAGE C)
check_type_size("long long" LONG_LONG_SIZE LANGUAGE C)
check_type_size("uintptr_t" UINTPTR_T_SIZE LANGUAGE C)
check_type_size("size_t"    SIZE_T_SIZE LANGUAGE C)

if(INT16_T_SIZE EQUAL 2)
	set(SIZE16 "int16_t")
elseif(SHORT_SIZE EQUAL 2)
	set(SIZE16 "short")
elseif(INT_SIZE EQUAL 2)
	set(SIZE16 "int")
else()
	message(FATAL_ERROR "Failed to find a signed 16-bit integer type.")
endif()

if(UINT16_T_SIZE EQUAL 2)
	set(USIZE16 "uint16_t")
elseif(U_INT16_T_SIZE EQUAL 2)
	set(USIZE16 "u_int16_t")
elseif(SHORT_SIZE EQUAL 2)
	set(USIZE16 "unsigned short")
elseif(INT_SIZE EQUAL 2)
	set(USIZE16 "unsigned int")
else()
	message(FATAL_ERROR "Failed to find an unsigned 16-bit integer type.")
endif()

if(INT32_T_SIZE EQUAL 4)
	set(SIZE32 "int32_t")
elseif(SHORT_SIZE EQUAL 4)
	set(SIZE32 "short")
elseif(INT_SIZE EQUAL 4)
	set(SIZE32 "int")
elseif(LONG_SIZE EQUAL 4)
	set(SIZE32 "long")
else()
	message(FATAL_ERROR "Failed to find a signed 32-bit integer type.")
endif()

if(UINT32_T_SIZE EQUAL 4)
	set(USIZE32 "uint32_t")
elseif(U_INT32_T_SIZE EQUAL 4)
	set(USIZE32 "u_int32_t")
elseif(SHORT_SIZE EQUAL 4)
	set(USIZE32 "unsigned short")
elseif(INT_SIZE EQUAL 4)
	set(USIZE32 "unsigned int")
elseif(LONG_SIZE EQUAL 4)
	set(USIZE32 "unsigned long")
else()
	message(FATAL_ERROR "Failed to find an unsigned 32-bit integer type.")
endif()

if(INT64_T_SIZE EQUAL 8)
	set(SIZE64 "int64_t")
elseif(SHORT_SIZE EQUAL 8)
	set(SIZE64 "short")
elseif(INT_SIZE EQUAL 8)
	set(SIZE64 "int")
elseif(LONG_SIZE EQUAL 8)
	set(SIZE64 "long")
elseif(LONG_LONG_SIZE EQUAL 8)
	set(SIZE64 "long long")
else()
	message(FATAL_ERROR "Failed to find a signed 64-bit integer type.")
endif()

if(UINT64_T_SIZE EQUAL 8)
	set(USIZE64 "uint64_t")
elseif(U_INT64_T_SIZE EQUAL 8)
	set(USIZE64 "u_int64_t")
elseif(SHORT_SIZE EQUAL 8)
	set(USIZE64 "unsigned short")
elseif(INT_SIZE EQUAL 8)
	set(USIZE64 "unsigned int")
elseif(LONG_SIZE EQUAL 8)
	set(USIZE64 "unsigned long")
elseif(LONG_LONG_SIZE EQUAL 8)
	set(USIZE64 "unsigned long long")
else()
	message(FATAL_ERROR "Failed to find an unsigned 64-bit integer type.")
endif()

if(CMAKE_SIZEOF_VOID_P EQUAL UINTPTR_T_SIZE)
	set(USIZEPTR "uintptr_t")
elseif(CMAKE_SIZEOF_VOID_P LESS_EQUAL 1)
	set(USIZEPTR "unsigned char")
elseif(CMAKE_SIZEOF_VOID_P LESS_EQUAL 2)
	set(USIZEPTR "${USIZE16}")
elseif(CMAKE_SIZEOF_VOID_P LESS_EQUAL 4)
	set(USIZEPTR "${USIZE32}")
elseif(CMAKE_SIZEOF_VOID_P LESS_EQUAL 8)
	set(USIZEPTR "${USIZE64}")
else()
	message(FATAL_ERROR "Failed to find an integer type that can fit a pointer.")
endif()

if(NOT SIZE_T_SIZE EQUAL 0 AND NOT SIZE_T_SIZE EQUAL "")
	set(USIZESIZE "size_t")
else()
	# should be close enough I guess
	set(USIZESIZE "${USIZEPTR}")
endif()

configure_file(include/vec/types.h.in include/vec/types.h @ONLY)

#########################################################################

target_sources(vec PUBLIC
	$<INSTALL_INTERFACE:vec/vec.h>
	$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/vec/vec.h>
	$<INSTALL_INTERFACE:vec/types.h>
	$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/vec/types.h>
	$<INSTALL_INTERFACE:vec/cpu.h>
	$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/vec/cpu.h>
)

target_compile_features(vec PRIVATE $<IF:$<COMPILE_FEATURES:c_std_11>,c_std_11,c_std_99>)
target_include_directories(vec PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_CURRENT_BINARY_DIR}/include")

# Installing

include(GNUInstallDirs)

install(TARGETS vec LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/vec/vec.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/vec")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/vec/impl/integer.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/vec/impl")

# pkg-config
configure_file(vec.pc.in vec.pc @ONLY)
install(FILES ${CMAKE_BINARY_DIR}/vec.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)