CMakeLists.txt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
  2. project(JoltPhysics CXX)
  3. # When turning this option on, the library will be compiled using doubles for positions. This allows for much bigger worlds.
  4. option(DOUBLE_PRECISION "Use double precision math" OFF)
  5. # When turning this option on, the library will be compiled with debug symbols
  6. option(GENERATE_DEBUG_SYMBOLS "Generate debug symbols" ON)
  7. # When turning this option on, the library will be compiled in such a way to attempt to keep the simulation deterministic across platforms
  8. option(CROSS_PLATFORM_DETERMINISTIC "Cross platform deterministic" OFF)
  9. # When turning this option on, the library will be compiled for ARM (aarch64-linux-gnu), requires compiling with clang
  10. option(CROSS_COMPILE_ARM "Cross compile to aarch64-linux-gnu" OFF)
  11. # 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.
  12. # Note that if you turn this on you need to use SET_INTERPROCEDURAL_OPTIMIZATION() or set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) to enable LTO specificly for your own project as well.
  13. # If you don't do this you may get an error: /usr/bin/ld: libJolt.a: error adding symbols: file format not recognized
  14. option(INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural optimizations" ON)
  15. # 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
  16. # and will enable floating point exceptions during simulation to detect divisions by zero.
  17. # Note that this currently only works using MSVC. Clang turns Float2 into a SIMD vector sometimes causing floating point exceptions (the option is ignored).
  18. option(FLOATING_POINT_EXCEPTIONS_ENABLED "Enable floating point exceptions" ON)
  19. # Number of bits to use in ObjectLayer. Can be 16 or 32.
  20. option(OBJECT_LAYER_BITS "Number of bits in ObjectLayer" 16)
  21. # Select X86 processor features to use (if everything is off it will be SSE2 compatible)
  22. option(USE_SSE4_1 "Enable SSE4.1" ON)
  23. option(USE_SSE4_2 "Enable SSE4.2" ON)
  24. option(USE_AVX "Enable AVX" ON)
  25. option(USE_AVX2 "Enable AVX2" ON)
  26. option(USE_AVX512 "Enable AVX512" OFF)
  27. option(USE_LZCNT "Enable LZCNT" ON)
  28. option(USE_TZCNT "Enable TZCNT" ON)
  29. option(USE_F16C "Enable F16C" ON)
  30. option(USE_FMADD "Enable FMADD" ON)
  31. # Enable all warnings
  32. option(ENABLE_ALL_WARNINGS "Enable all warnings and warnings as errors" ON)
  33. include(CMakeDependentOption)
  34. # Ability to toggle between the static and DLL versions of the MSVC runtime library
  35. # Windows Store only supports the DLL version
  36. cmake_dependent_option(USE_STATIC_MSVC_RUNTIME_LIBRARY "Use the static MSVC runtime library" ON "MSVC;NOT WINDOWS_STORE" OFF)
  37. # Determine which configurations exist
  38. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  39. set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Distribution")
  40. elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
  41. set(CMAKE_CONFIGURATION_TYPES "Debug;Release;ReleaseASAN;ReleaseUBSAN;ReleaseCoverage;Distribution")
  42. endif()
  43. if (("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore") AND NOT MINGW)
  44. # Fill in the path to the asan libraries
  45. set(CLANG_LIB_PATH "\"$(VSInstallDir)\\VC\\Tools\\Llvm\\x64\\lib\\clang\\${CMAKE_CXX_COMPILER_VERSION}\\lib\\windows\"")
  46. # 64 bit architecture
  47. set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE "x64")
  48. # Set runtime library
  49. if (USE_STATIC_MSVC_RUNTIME_LIBRARY)
  50. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  51. endif()
  52. # Set general compiler flags
  53. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus /Gm- /MP /nologo /diagnostics:classic /FC /fp:except- /Zc:inline")
  54. # Enable warnings
  55. if (ENABLE_ALL_WARNINGS)
  56. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /WX")
  57. endif()
  58. # Optionally generate debug symbols
  59. if (GENERATE_DEBUG_SYMBOLS)
  60. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
  61. endif()
  62. # Remove any existing compiler flag that enables RTTI
  63. string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
  64. # Set compiler flag for disabling RTTI
  65. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
  66. if ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM")
  67. # On ARM the exception handling flag is missing which causes warnings
  68. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
  69. endif()
  70. # Set compiler flags for various configurations
  71. set(CMAKE_CXX_FLAGS_DEBUG "/GS /Od /Ob0 /RTC1")
  72. set(CMAKE_CXX_FLAGS_RELEASE "/GS- /Gy /O2 /Oi /Ot")
  73. set(CMAKE_CXX_FLAGS_DISTRIBUTION "/GS- /Gy /O2 /Oi /Ot")
  74. set(CMAKE_CXX_FLAGS_RELEASEASAN "-fsanitize=address /Od")
  75. set(CMAKE_CXX_FLAGS_RELEASEUBSAN "-fsanitize=undefined,implicit-conversion,float-divide-by-zero,local-bounds -fno-sanitize-recover=all")
  76. set(CMAKE_CXX_FLAGS_RELEASECOVERAGE "-fprofile-instr-generate -fcoverage-mapping")
  77. # Set linker flags
  78. set(CMAKE_EXE_LINKER_FLAGS "/SUBSYSTEM:WINDOWS /ignore:4221 /DEBUG:FASTLINK")
  79. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  80. if (CROSS_PLATFORM_DETERMINISTIC)
  81. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise")
  82. else()
  83. 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
  84. endif()
  85. elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
  86. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /showFilenames")
  87. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") # Clang emits warnings about unused arguments such as /MP and /GL
  88. 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")
  89. set(CMAKE_EXE_LINKER_FLAGS_RELEASEUBSAN "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
  90. set(CMAKE_EXE_LINKER_FLAGS_RELEASECOVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LIBPATH:${CLANG_LIB_PATH}")
  91. endif()
  92. elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS" OR MINGW OR EMSCRIPTEN)
  93. # Set general compiler flags
  94. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I.")
  95. # Enable warnings
  96. if (ENABLE_ALL_WARNINGS)
  97. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
  98. endif()
  99. # Optionally generate debug symbols
  100. if (GENERATE_DEBUG_SYMBOLS)
  101. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
  102. endif()
  103. if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  104. # Somehow -Wcomment doesn't want to be turned off from code and we need this because Doxygen MathJax uses it
  105. # Also disable -Wstringop-overflow or it will generate false positives that can't be disabled from code when link-time optimizations are enabled
  106. # 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
  107. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment -Wno-stringop-overflow -ffp-contract=off")
  108. else()
  109. # Do not use -ffast-math since it cannot be turned off in a single compilation unit under clang, see Core.h
  110. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffp-model=precise")
  111. # On clang 14 and later we can turn off float contraction through a pragma, older versions and deterministic versions need it off always, see Core.h
  112. if (CMAKE_CXX_COMPILER_VERSION LESS 14 OR CROSS_PLATFORM_DETERMINISTIC)
  113. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffp-contract=off")
  114. endif()
  115. endif()
  116. # Cross compiler flags
  117. if (CROSS_COMPILE_ARM)
  118. set(CMAKE_CXX_FLAGS "--target=aarch64-linux-gnu ${CMAKE_CXX_FLAGS}")
  119. endif()
  120. # Set compiler flags for various configurations
  121. set(CMAKE_CXX_FLAGS_DEBUG "")
  122. set(CMAKE_CXX_FLAGS_RELEASE "-O3")
  123. set(CMAKE_CXX_FLAGS_DISTRIBUTION "-O3")
  124. set(CMAKE_CXX_FLAGS_RELEASEASAN "-fsanitize=address")
  125. set(CMAKE_CXX_FLAGS_RELEASEUBSAN "-fsanitize=undefined,implicit-conversion,float-divide-by-zero,local-bounds -fno-sanitize-recover=all")
  126. set(CMAKE_CXX_FLAGS_RELEASECOVERAGE "-fprofile-instr-generate -fcoverage-mapping")
  127. # Set linker flags
  128. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
  129. endif()
  130. # Set linker flags
  131. set(CMAKE_EXE_LINKER_FLAGS_DISTRIBUTION "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
  132. # Enable link time optimization in Release and Distribution mode if requested and available
  133. function(SET_INTERPROCEDURAL_OPTIMIZATION)
  134. set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE OFF PARENT_SCOPE)
  135. set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DISTRIBUTION OFF PARENT_SCOPE)
  136. # On ARM, whole program optimization triggers an internal compiler error during code gen, so we don't turn it on
  137. if (INTERPROCEDURAL_OPTIMIZATION AND NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM64") AND NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM"))
  138. include(CheckIPOSupported)
  139. check_ipo_supported(RESULT IS_IPO_SUPPORTED OUTPUT IPO_CHECK_OUTPUT)
  140. if (IS_IPO_SUPPORTED)
  141. set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON PARENT_SCOPE)
  142. set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DISTRIBUTION ON PARENT_SCOPE)
  143. else()
  144. message(WARNING "Interprocedural optimizations are not supported: ${IPO_CHECK_OUTPUT}")
  145. endif()
  146. endif()
  147. endfunction()
  148. SET_INTERPROCEDURAL_OPTIMIZATION()
  149. # Set repository root
  150. set(PHYSICS_REPO_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../)
  151. # Make Jolt Library
  152. include(${PHYSICS_REPO_ROOT}/Jolt/Jolt.cmake)
  153. if (IOS)
  154. # Ensure that we enable SSE4.2 for the x86_64 build, CMAKE_SYSTEM_PROCESSOR is not set for iOS
  155. set_property(TARGET Jolt PROPERTY XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=x86_64] "$(inherited) -msse4.2 -mpopcnt")
  156. endif()
  157. # Install Jolt library and includes
  158. install(TARGETS Jolt DESTINATION lib)
  159. foreach(SRC_FILE ${JOLT_PHYSICS_SRC_FILES})
  160. string(REPLACE ${PHYSICS_REPO_ROOT} "" RELATIVE_SRC_FILE ${SRC_FILE})
  161. get_filename_component(DESTINATION_PATH ${RELATIVE_SRC_FILE} DIRECTORY)
  162. if (NOT RELATIVE_SRC_FILE MATCHES "\.cpp")
  163. install(FILES ${SRC_FILE} DESTINATION include/${DESTINATION_PATH})
  164. endif()
  165. endforeach()
  166. # Check if we're the root CMakeLists.txt, if not we are included by another CMake file and we should disable everything except for the main library
  167. if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
  168. # Ability to turn ON/OFF individual applications
  169. option(TARGET_UNIT_TESTS "Build Unit Tests" ON)
  170. option(TARGET_HELLO_WORLD "Build Hello World" ON)
  171. option(TARGET_PERFORMANCE_TEST "Build Performance Test" ON)
  172. option(TARGET_SAMPLES "Build Samples" ON)
  173. option(TARGET_VIEWER "Build JoltViewer" ON)
  174. if (TARGET_UNIT_TESTS)
  175. # Create UnitTests executable
  176. include(${PHYSICS_REPO_ROOT}/UnitTests/UnitTests.cmake)
  177. add_executable(UnitTests ${UNIT_TESTS_SRC_FILES})
  178. target_include_directories(UnitTests PUBLIC ${UNIT_TESTS_ROOT})
  179. target_link_libraries(UnitTests LINK_PUBLIC Jolt)
  180. target_precompile_headers(UnitTests PRIVATE ${JOLT_PHYSICS_ROOT}/Jolt.h)
  181. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  182. target_link_options(UnitTests PUBLIC "/SUBSYSTEM:CONSOLE")
  183. endif()
  184. if (IOS)
  185. # Set the bundle information
  186. set_property(TARGET UnitTests PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/iOS/UnitTestsInfo.plist")
  187. set_property(TARGET UnitTests PROPERTY XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.joltphysics.unittests")
  188. # Ensure that we enable SSE4.2 for the x86_64 build, CMAKE_SYSTEM_PROCESSOR is not set for iOS
  189. set_property(TARGET UnitTests PROPERTY XCODE_ATTRIBUTE_OTHER_CPLUSPLUSFLAGS[arch=x86_64] "$(inherited) -msse4.2 -mpopcnt")
  190. endif()
  191. # Register unit tests as a test so that it can be run with:
  192. # ctest --output-on-failure
  193. enable_testing()
  194. add_test(UnitTests UnitTests)
  195. endif()
  196. if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
  197. if (TARGET_HELLO_WORLD)
  198. # Example 'Hello World' application
  199. include(${PHYSICS_REPO_ROOT}/HelloWorld/HelloWorld.cmake)
  200. add_executable(HelloWorld ${HELLO_WORLD_SRC_FILES})
  201. target_include_directories(HelloWorld PUBLIC ${HELLO_WORLD_ROOT})
  202. target_link_libraries(HelloWorld LINK_PUBLIC Jolt)
  203. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  204. target_link_options(HelloWorld PUBLIC "/SUBSYSTEM:CONSOLE")
  205. endif()
  206. endif()
  207. if (TARGET_PERFORMANCE_TEST)
  208. # Performance Test application
  209. include(${PHYSICS_REPO_ROOT}/PerformanceTest/PerformanceTest.cmake)
  210. add_executable(PerformanceTest ${PERFORMANCE_TEST_SRC_FILES})
  211. target_include_directories(PerformanceTest PUBLIC ${PERFORMANCE_TEST_ROOT})
  212. target_link_libraries(PerformanceTest LINK_PUBLIC Jolt)
  213. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT MINGW)
  214. target_link_options(PerformanceTest PUBLIC "/SUBSYSTEM:CONSOLE")
  215. endif()
  216. set_property(TARGET PerformanceTest PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PHYSICS_REPO_ROOT}")
  217. # Copy the assets folder
  218. add_custom_command(TARGET PerformanceTest PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PHYSICS_REPO_ROOT}/Assets/ $<TARGET_FILE_DIR:PerformanceTest>/Assets/)
  219. endif()
  220. endif()
  221. if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" AND NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM")) # ARM 32-bit is missing dinput8.lib
  222. # Windows only targets
  223. if (TARGET_SAMPLES OR TARGET_VIEWER)
  224. include(${PHYSICS_REPO_ROOT}/TestFramework/TestFramework.cmake)
  225. endif()
  226. if (TARGET_SAMPLES)
  227. include(${PHYSICS_REPO_ROOT}/Samples/Samples.cmake)
  228. endif()
  229. if (TARGET_VIEWER)
  230. include(${PHYSICS_REPO_ROOT}/JoltViewer/JoltViewer.cmake)
  231. endif()
  232. endif()
  233. endif()