Ver código fonte

Moved detection of instruction sets to Jolt.cmake (#421)

This ensures that when using CMake FetchContent the proper defines are propagated to child projects which avoids linker errors or run-time crashes
Jorrit Rouwe 2 anos atrás
pai
commit
33f94be387
3 arquivos alterados com 92 adições e 85 exclusões
  1. 6 85
      Build/CMakeLists.txt
  2. 83 0
      Jolt/Jolt.cmake
  3. 3 0
      UnitTests/UnitTestFramework.cpp

+ 6 - 85
Build/CMakeLists.txt

@@ -24,6 +24,11 @@ option(CROSS_COMPILE_ARM "Cross compile to aarch64-linux-gnu" OFF)
 # When turning this option on, the library will be compiled with interprocedural optimizations enabled, also known as link-time optimizations or link-time code generation
 option(INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural optimizations" ON)
 
+# When turning this on, in Debug and Release mode, the library will emit extra code to ensure that the 4th component of a 3-vector is kept the same as the 3rd component 
+# and will enable floating point exceptions during simulation to detect divisions by zero. 
+# Note that this currently only works using MSVC. Clang turns Float2 into a SIMD vector sometimes causing floating point exceptions (the option is ignored).
+option(FLOATING_POINT_EXCEPTIONS_ENABLED "Enable floating point exceptions" ON)
+
 # Select X86 processor features to use (if everything is off it will be SSE2 compatible)
 option(USE_SSE4_1 "Enable SSE4.1" ON)
 option(USE_SSE4_2 "Enable SSE4.2" ON)
@@ -97,63 +102,9 @@ if (("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR "${CMAKE_SYSTEM_NAME}" STREQUA
 		else()
 			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast") # Clang doesn't use fast math because it cannot be turned off inside a single compilation unit
 		endif()
-		if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86" OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
-			if (USE_AVX512)
-				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX512")
-			elseif (USE_AVX2)
-				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
-			elseif (USE_AVX)
-				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
-			endif()	
-			if (USE_SSE4_1)
-				add_compile_definitions(JPH_USE_SSE4_1)
-			endif()
-			if (USE_SSE4_2)
-				add_compile_definitions(JPH_USE_SSE4_2)
-			endif()
-			if (USE_LZCNT)
-				add_compile_definitions(JPH_USE_LZCNT)
-			endif()
-			if (USE_TZCNT)
-				add_compile_definitions(JPH_USE_TZCNT)
-			endif()
-			if (USE_F16C)
-				add_compile_definitions(JPH_USE_F16C)
-			endif()
-			if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
-				add_compile_definitions(JPH_USE_FMADD)
-			endif()
-		endif()
-		set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DJPH_FLOATING_POINT_EXCEPTIONS_ENABLED") # Clang turns Float2 into a vector sometimes causing floating point exceptions
-		set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /DJPH_FLOATING_POINT_EXCEPTIONS_ENABLED")
 	elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
 		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /showFilenames")
 		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") # Clang emits warnings about unused arguments such as /MP and /GL
-		if (USE_AVX512)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vl -mavx512dq -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
-		elseif (USE_AVX2)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
-		elseif (USE_AVX)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx -mpopcnt")
-		elseif (USE_SSE4_2)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 -mpopcnt")
-		elseif (USE_SSE4_1)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
-		else()
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
-		endif()
-		if (USE_LZCNT)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlzcnt")
-		endif()
-		if (USE_TZCNT)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi")
-		endif()
-		if (USE_F16C)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
-		endif()
-		if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma")
-		endif()
 		set(CMAKE_EXE_LINKER_FLAGS_RELEASEASAN "/SUBSYSTEM:CONSOLE /LIBPATH:${CLANG_LIB_PATH} clang_rt.asan-x86_64.lib -wholearchive:clang_rt.asan-x86_64.lib clang_rt.asan_cxx-x86_64.lib -wholearchive:clang_rt.asan_cxx-x86_64.lib")
 		set(CMAKE_EXE_LINKER_FLAGS_RELEASEUBSAN "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
 		set(CMAKE_EXE_LINKER_FLAGS_RELEASECOVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
@@ -182,39 +133,9 @@ elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQU
 		endif()
 	endif()
 
-	# Platform specific compiler flags
+	# Cross compiler flags
 	if (CROSS_COMPILE_ARM)
 		set(CMAKE_CXX_FLAGS "--target=aarch64-linux-gnu ${CMAKE_CXX_FLAGS}")
-	elseif (CMAKE_OSX_ARCHITECTURES MATCHES "arm64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
-		# ARM64
-		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
-	elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
-		# X64
-		if (USE_AVX512)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vl -mavx512dq -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
-		elseif (USE_AVX2)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
-		elseif (USE_AVX)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx -mpopcnt")
-		elseif (USE_SSE4_2)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 -mpopcnt")
-		elseif (USE_SSE4_1)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
-		else()
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
-		endif()
-		if (USE_LZCNT)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlzcnt")
-		endif()
-		if (USE_TZCNT)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi")
-		endif()
-		if (USE_F16C)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
-		endif()
-		if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
-			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma")
-		endif()
 	endif()
 
 	# Set compiler flags for various configurations

+ 83 - 0
Jolt/Jolt.cmake

@@ -424,6 +424,12 @@ target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseASAN>:NDEBUG;JPH_PROFI
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseUBSAN>:NDEBUG;JPH_PROFILE_ENABLED;JPH_DEBUG_RENDERER>")
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseCoverage>:NDEBUG>")
 
+# Setting floating point exceptions
+if (FLOATING_POINT_EXCEPTIONS_ENABLED AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+	target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Debug>:JPH_FLOATING_POINT_EXCEPTIONS_ENABLED>")
+	target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Release>:JPH_FLOATING_POINT_EXCEPTIONS_ENABLED>")
+endif()
+
 # Setting double precision flag
 if (DOUBLE_PRECISION)
 	target_compile_definitions(Jolt PUBLIC JPH_DOUBLE_PRECISION)
@@ -433,3 +439,80 @@ endif()
 if (CROSS_PLATFORM_DETERMINISTIC)
 	target_compile_definitions(Jolt PUBLIC JPH_CROSS_PLATFORM_DETERMINISTIC)
 endif()
+
+# Emit the instruction set definitions to ensure that child projects use the same settings even if they override the used instruction sets (a mismatch causes link errors)
+function(EMIT_X86_INSTRUCTION_SET_DEFINITIONS)
+	if (USE_AVX512)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_AVX512)
+	endif()
+	if (USE_AVX2)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_AVX2)
+	endif()
+	if (USE_AVX)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_AVX)
+	endif()	
+	if (USE_SSE4_1)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_SSE4_1)
+	endif()
+	if (USE_SSE4_2)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_SSE4_2)
+	endif()
+	if (USE_LZCNT)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_LZCNT)
+	endif()
+	if (USE_TZCNT)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_TZCNT)
+	endif()
+	if (USE_F16C)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_F16C)
+	endif()
+	if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
+		target_compile_definitions(Jolt PUBLIC JPH_USE_FMADD)
+	endif()
+endfunction()
+
+# Add the compiler commandline flags to select the right instruction sets
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+	if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86" OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
+		if (USE_AVX512)
+			target_compile_options(Jolt PUBLIC /arch:AVX512)
+		elseif (USE_AVX2)
+			target_compile_options(Jolt PUBLIC /arch:AVX2)
+		elseif (USE_AVX)
+			target_compile_options(Jolt PUBLIC /arch:AVX)
+		endif()
+		EMIT_X86_INSTRUCTION_SET_DEFINITIONS()
+	endif()
+else()
+	if (CROSS_COMPILE_ARM OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
+		# ARM64 uses no special commandline flags
+	elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
+		# x64
+		if (USE_AVX512)
+			target_compile_options(Jolt PUBLIC -mavx512f -mavx512vl -mavx512dq -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c)
+		elseif (USE_AVX2)
+			target_compile_options(Jolt PUBLIC -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c)
+		elseif (USE_AVX)
+			target_compile_options(Jolt PUBLIC -mavx -mpopcnt)
+		elseif (USE_SSE4_2)
+			target_compile_options(Jolt PUBLIC -msse4.2 -mpopcnt)
+		elseif (USE_SSE4_1)
+			target_compile_options(Jolt PUBLIC -msse4.1)
+		else()
+			target_compile_options(Jolt PUBLIC -msse2)
+		endif()
+		if (USE_LZCNT)
+			target_compile_options(Jolt PUBLIC -mlzcnt)
+		endif()
+		if (USE_TZCNT)
+			target_compile_options(Jolt PUBLIC -mbmi)
+		endif()
+		if (USE_F16C)
+			target_compile_options(Jolt PUBLIC -mf16c)
+		endif()
+		if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
+			target_compile_options(Jolt PUBLIC -mfma)
+		endif()
+		EMIT_X86_INSTRUCTION_SET_DEFINITIONS()
+	endif()
+endif()

+ 3 - 0
UnitTests/UnitTestFramework.cpp

@@ -211,6 +211,9 @@ int main(int argc, char** argv)
 #endif
 #ifdef JPH_CROSS_PLATFORM_DETERMINISTIC
 	std::cout << "(Cross Platform Deterministic)";
+#endif
+#ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
+	std::cout << "(FP Exceptions)";
 #endif
 	std::cout << std::endl;