CMakeLists.txt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
  2. project(JoltPhysics CXX)
  3. # Ability to turn ON/OFF individual applications
  4. option(TARGET_UNIT_TESTS "Build Unit Tests" ON)
  5. option(TARGET_HELLO_WORLD "Build Hello World" ON)
  6. option(TARGET_PERFORMANCE_TEST "Build Performance Test" ON)
  7. option(TARGET_SAMPLES "Build Samples" ON)
  8. option(TARGET_VIEWER "Build JoltViewer" ON)
  9. # When turning this option on, the library will be compiled in such a way to attempt to keep the simulation deterministic across platforms
  10. option(CROSS_PLATFORM_DETERMINISTIC "Cross platform deterministic" OFF)
  11. # When turning this option on, the library will be compiled for ARM (aarch64-linux-gnu), requires compiling with clang
  12. option(CROSS_COMPILE_ARM "Cross compile to aarch64-linux-gnu" OFF)
  13. # Select X86 processor features to use (if everything is off it will be SSE2 compatible)
  14. option(USE_SSE4_1 "Enable SSE4.1" ON)
  15. option(USE_SSE4_2 "Enable SSE4.2" ON)
  16. option(USE_AVX "Enable AVX" ON)
  17. option(USE_AVX2 "Enable AVX2" ON)
  18. option(USE_AVX512 "Enable AVX512" OFF)
  19. option(USE_LZCNT "Enable LZCNT" ON)
  20. option(USE_TZCNT "Enable TZCNT" ON)
  21. option(USE_F16C "Enable F16C" ON)
  22. option(USE_FMADD "Enable FMADD" ON)
  23. include(CMakeDependentOption)
  24. # Ability to toggle between the static and DLL versions of the MSVC runtime library
  25. # Windows Store only supports the DLL version
  26. cmake_dependent_option(USE_STATIC_MSVC_RUNTIME_LIBRARY "Use the static MSVC runtime library" ON "MSVC;NOT WINDOWS_STORE" OFF)
  27. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  28. set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Distribution")
  29. elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
  30. set(CMAKE_CONFIGURATION_TYPES "Debug;Release;ReleaseASAN;ReleaseUBSAN;ReleaseCoverage;Distribution")
  31. endif()
  32. if (("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore") AND NOT MINGW)
  33. # Fill in the path to the asan libraries
  34. set(CLANG_LIB_PATH "\"$(VSInstallDir)\\VC\\Tools\\Llvm\\x64\\lib\\clang\\${CMAKE_CXX_COMPILER_VERSION}\\lib\\windows\"")
  35. # 64 bit architecture
  36. set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE "x64")
  37. # Set runtime library
  38. if (USE_STATIC_MSVC_RUNTIME_LIBRARY)
  39. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  40. else()
  41. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
  42. endif()
  43. # Set general compiler flags
  44. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Zc:__cplusplus /Gm- /Wall /WX /MP /nologo /diagnostics:classic /FC /fp:except- /Zc:inline /Zi")
  45. # Remove any existing compiler flag that enables RTTI
  46. string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
  47. # Set compiler flag for disabling RTTI
  48. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
  49. if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM")
  50. # On ARM the exception handling flag is missing which causes warnings
  51. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
  52. endif()
  53. # Set compiler flags for various configurations
  54. set(CMAKE_CXX_FLAGS_DEBUG "/GS /Od /Ob0 /RTC1")
  55. set(CMAKE_CXX_FLAGS_RELEASE "/GS- /Gy /O2 /Oi /Ot")
  56. set(CMAKE_CXX_FLAGS_DISTRIBUTION "/GS- /Gy /O2 /Oi /Ot")
  57. set(CMAKE_CXX_FLAGS_RELEASEASAN "-fsanitize=address /Od")
  58. set(CMAKE_CXX_FLAGS_RELEASEUBSAN "-fsanitize=undefined,implicit-conversion,float-divide-by-zero,local-bounds -fno-sanitize-recover=all")
  59. set(CMAKE_CXX_FLAGS_RELEASECOVERAGE "-fprofile-instr-generate -fcoverage-mapping")
  60. if (NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM64") AND NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM"))
  61. # On ARM, whole program optimization triggers an internal compiler error during code gen, so we don't turn it on
  62. set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
  63. set(CMAKE_CXX_FLAGS_DISTRIBUTION "${CMAKE_CXX_FLAGS_DISTRIBUTION} /GL")
  64. endif()
  65. # Set linker flags
  66. set(CMAKE_EXE_LINKER_FLAGS "/SUBSYSTEM:WINDOWS /ignore:4221 /DEBUG:FASTLINK")
  67. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  68. if (CROSS_PLATFORM_DETERMINISTIC)
  69. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise")
  70. else()
  71. 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
  72. endif()
  73. if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86" OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
  74. if (USE_AVX512)
  75. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX512")
  76. elseif (USE_AVX2)
  77. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
  78. elseif (USE_AVX)
  79. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
  80. endif()
  81. if (USE_SSE4_1)
  82. add_compile_definitions(JPH_USE_SSE4_1)
  83. endif()
  84. if (USE_SSE4_2)
  85. add_compile_definitions(JPH_USE_SSE4_2)
  86. endif()
  87. if (USE_LZCNT)
  88. add_compile_definitions(JPH_USE_LZCNT)
  89. endif()
  90. if (USE_TZCNT)
  91. add_compile_definitions(JPH_USE_TZCNT)
  92. endif()
  93. if (USE_F16C)
  94. add_compile_definitions(JPH_USE_F16C)
  95. endif()
  96. if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
  97. add_compile_definitions(JPH_USE_FMADD)
  98. endif()
  99. endif()
  100. 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
  101. set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /DJPH_FLOATING_POINT_EXCEPTIONS_ENABLED")
  102. set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/INCREMENTAL:NO /LTCG:incremental /OPT:ICF /OPT:REF")
  103. set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
  104. elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
  105. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /showFilenames")
  106. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") # Clang emits warnings about unused arguments such as /MP and /GL
  107. if (USE_AVX512)
  108. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vl -mavx512dq -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
  109. elseif (USE_AVX2)
  110. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
  111. elseif (USE_AVX)
  112. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx -mpopcnt")
  113. elseif (USE_SSE4_2)
  114. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 -mpopcnt")
  115. elseif (USE_SSE4_1)
  116. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
  117. else()
  118. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
  119. endif()
  120. if (USE_LZCNT)
  121. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlzcnt")
  122. endif()
  123. if (USE_TZCNT)
  124. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi")
  125. endif()
  126. if (USE_F16C)
  127. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
  128. endif()
  129. if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
  130. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma")
  131. endif()
  132. 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")
  133. set(CMAKE_EXE_LINKER_FLAGS_RELEASEUBSAN "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
  134. set(CMAKE_EXE_LINKER_FLAGS_RELEASECOVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
  135. endif()
  136. elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS" OR MINGW OR EMSCRIPTEN)
  137. # Set general compiler flags
  138. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++17 -I. -Wall -Werror")
  139. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  140. # Somehow -Wcomment doesn't want to be turned off from code and we need this because Doxygen MathJax uses it
  141. # Also turn off automatic fused multiply add contractions, there doesn't seem to be a way to do this selectively through the macro JPH_PRECISE_MATH_OFF
  142. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -ffp-contract=off")
  143. else()
  144. # Do not use -ffast-math or -ffp-contract=on since it cannot be turned off in a single compilation unit under clang, see Core.h
  145. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffp-model=precise -ffp-contract=off")
  146. endif()
  147. # Platform specific compiler flags
  148. if (CROSS_COMPILE_ARM)
  149. set(CMAKE_CXX_FLAGS "--target=aarch64-linux-gnu ${CMAKE_CXX_FLAGS}")
  150. elseif (CMAKE_OSX_ARCHITECTURES MATCHES "arm64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
  151. # ARM64
  152. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  153. elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
  154. # X64
  155. if (USE_AVX512)
  156. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vl -mavx512dq -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
  157. elseif (USE_AVX2)
  158. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -mbmi -mpopcnt -mlzcnt -mf16c")
  159. elseif (USE_AVX)
  160. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx -mpopcnt")
  161. elseif (USE_SSE4_2)
  162. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 -mpopcnt")
  163. elseif (USE_SSE4_1)
  164. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
  165. else()
  166. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
  167. endif()
  168. if (USE_LZCNT)
  169. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlzcnt")
  170. endif()
  171. if (USE_TZCNT)
  172. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mbmi")
  173. endif()
  174. if (USE_F16C)
  175. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
  176. endif()
  177. if (USE_FMADD AND NOT CROSS_PLATFORM_DETERMINISTIC)
  178. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma")
  179. endif()
  180. endif()
  181. # Set compiler flags for various configurations
  182. set(CMAKE_CXX_FLAGS_RELEASE "-O3")
  183. set(CMAKE_CXX_FLAGS_DISTRIBUTION "-O3")
  184. set(CMAKE_CXX_FLAGS_RELEASEASAN "-fsanitize=address")
  185. set(CMAKE_CXX_FLAGS_RELEASEUBSAN "-fsanitize=undefined,implicit-conversion,float-divide-by-zero,local-bounds -fno-sanitize-recover=all")
  186. set(CMAKE_CXX_FLAGS_RELEASECOVERAGE "-fprofile-instr-generate -fcoverage-mapping")
  187. # Set linker flags
  188. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
  189. endif()
  190. # Setting to attempt cross platform determinism
  191. if (CROSS_PLATFORM_DETERMINISTIC)
  192. add_compile_definitions(JPH_CROSS_PLATFORM_DETERMINISTIC)
  193. endif()
  194. # Set linker flags
  195. set(CMAKE_EXE_LINKER_FLAGS_DISTRIBUTION "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
  196. # Set repository root
  197. set(PHYSICS_REPO_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../)
  198. # Make Jolt Library
  199. include(${PHYSICS_REPO_ROOT}/Jolt/Jolt.cmake)
  200. if (IOS)
  201. # Ensure that we enable SSE4.2 for the x86_64 build, CMAKE_SYSTEM_PROCESSOR is not set for iOS
  202. set_property(TARGET Jolt PROPERTY XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=x86_64] "$(inherited) -msse4.2 -mpopcnt")
  203. endif()
  204. if (TARGET_UNIT_TESTS)
  205. # Create UnitTests executable
  206. include(${PHYSICS_REPO_ROOT}/UnitTests/UnitTests.cmake)
  207. add_executable(UnitTests ${UNIT_TESTS_SRC_FILES})
  208. target_include_directories(UnitTests PUBLIC ${UNIT_TESTS_ROOT})
  209. target_link_libraries(UnitTests LINK_PUBLIC Jolt)
  210. target_precompile_headers(UnitTests PRIVATE ${JOLT_PHYSICS_ROOT}/Jolt.h)
  211. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  212. target_link_options(UnitTests PUBLIC "/SUBSYSTEM:CONSOLE")
  213. endif()
  214. if (IOS)
  215. # Set the bundle information
  216. set_property(TARGET UnitTests PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/iOS/UnitTestsInfo.plist")
  217. set_property(TARGET UnitTests PROPERTY XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.joltphysics.unittests")
  218. # Ensure that we enable SSE4.2 for the x86_64 build, CMAKE_SYSTEM_PROCESSOR is not set for iOS
  219. set_property(TARGET UnitTests PROPERTY XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=x86_64] "$(inherited) -msse4.2 -mpopcnt")
  220. endif()
  221. # Register unit tests as a test so that it can be run with:
  222. # ctest --output-on-failure
  223. enable_testing()
  224. add_test(UnitTests UnitTests)
  225. endif()
  226. if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
  227. if (TARGET_HELLO_WORLD)
  228. # Example 'Hello World' application
  229. include(${PHYSICS_REPO_ROOT}/HelloWorld/HelloWorld.cmake)
  230. add_executable(HelloWorld ${HELLO_WORLD_SRC_FILES})
  231. target_include_directories(HelloWorld PUBLIC ${HELLO_WORLD_ROOT})
  232. target_link_libraries(HelloWorld LINK_PUBLIC Jolt)
  233. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  234. target_link_options(HelloWorld PUBLIC "/SUBSYSTEM:CONSOLE")
  235. endif()
  236. endif()
  237. if (TARGET_PERFORMANCE_TEST)
  238. # Performance Test application
  239. include(${PHYSICS_REPO_ROOT}/PerformanceTest/PerformanceTest.cmake)
  240. add_executable(PerformanceTest ${PERFORMANCE_TEST_SRC_FILES})
  241. target_include_directories(PerformanceTest PUBLIC ${PERFORMANCE_TEST_ROOT})
  242. target_link_libraries(PerformanceTest LINK_PUBLIC Jolt)
  243. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  244. target_link_options(PerformanceTest PUBLIC "/SUBSYSTEM:CONSOLE")
  245. endif()
  246. set_property(TARGET PerformanceTest PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PHYSICS_REPO_ROOT}")
  247. # Copy the assets folder
  248. add_custom_command(TARGET PerformanceTest PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PHYSICS_REPO_ROOT}/Assets/ $<TARGET_FILE_DIR:PerformanceTest>/Assets/)
  249. endif()
  250. endif()
  251. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM")) # ARM 32-bit is missing dinput8.lib
  252. # Windows only targets
  253. if (TARGET_SAMPLES OR TARGET_VIEWER)
  254. include(${PHYSICS_REPO_ROOT}/TestFramework/TestFramework.cmake)
  255. endif()
  256. if (TARGET_SAMPLES)
  257. include(${PHYSICS_REPO_ROOT}/Samples/Samples.cmake)
  258. endif()
  259. if (TARGET_VIEWER)
  260. include(${PHYSICS_REPO_ROOT}/JoltViewer/JoltViewer.cmake)
  261. endif()
  262. endif()