view CMakeLists.txt @ 23:e26874655738

*: huge refactor, new major release (hahaha) I keep finding things that are broken... The problem NOW was that vec would unintentionally build some functions with extended instruction sets, which is Bad and would mean that for all intents and purposes the CPU detection was completely broken. Now vec is no longer header only either. Boohoo. However this gives a lot more flexibility to vec since we no longer want or need to care about C++ crap. The NEON and Altivec implementations have not been updated which means they won't compile hence why they're commented out in the cmake build file.
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 02:52:40 -0500
parents 41dd962abdd1
children 92156fe32755
line wrap: on
line source

cmake_minimum_required(VERSION 3.23)

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

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)