diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a02462..e545777 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ option(MCRF_SANITIZE_ADDRESS "Build with AddressSanitizer" OFF) option(MCRF_SANITIZE_UNDEFINED "Build with UBSan" OFF) option(MCRF_SANITIZE_THREAD "Build with ThreadSanitizer" OFF) option(MCRF_DEBUG_PYTHON "Link against debug CPython from __lib_debug/" OFF) +option(MCRF_FREE_THREADED_PYTHON "Link against free-threaded CPython (python3.14t)" OFF) option(MCRF_WASM_DEBUG "Build WASM with DWARF debug info and source maps" OFF) # Validate mutually exclusive sanitizers @@ -209,7 +210,9 @@ elseif(MCRF_HEADLESS) endif() else() # Unix/Linux headless build - if(MCRF_DEBUG_PYTHON) + if(MCRF_FREE_THREADED_PYTHON) + set(PYTHON_LIB python3.14t) + elseif(MCRF_DEBUG_PYTHON) set(PYTHON_LIB python3.14d) else() set(PYTHON_LIB python3.14) @@ -219,7 +222,7 @@ elseif(MCRF_HEADLESS) ${PYTHON_LIB} m dl util pthread) include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux) - if(MCRF_DEBUG_PYTHON) + if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON) link_directories(${CMAKE_SOURCE_DIR}/__lib_debug) endif() link_directories(${CMAKE_SOURCE_DIR}/__lib) @@ -268,7 +271,9 @@ elseif(WIN32) link_directories(${CMAKE_SOURCE_DIR}/__lib) else() # Unix/Linux build - if(MCRF_DEBUG_PYTHON) + if(MCRF_FREE_THREADED_PYTHON) + set(PYTHON_LIB python3.14t) + elseif(MCRF_DEBUG_PYTHON) set(PYTHON_LIB python3.14d) else() set(PYTHON_LIB python3.14) @@ -283,7 +288,7 @@ else() m dl util pthread ${OPENGL_LIBRARIES}) include_directories(${CMAKE_SOURCE_DIR}/deps/platform/linux) - if(MCRF_DEBUG_PYTHON) + if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON) link_directories(${CMAKE_SOURCE_DIR}/__lib_debug) endif() link_directories(${CMAKE_SOURCE_DIR}/__lib) @@ -329,10 +334,15 @@ if(MCRF_SANITIZE_THREAD) endif() # Enable Py_DEBUG when linking against debug CPython (matches pydebug ABI) -if(MCRF_DEBUG_PYTHON) +if(MCRF_DEBUG_PYTHON OR MCRF_FREE_THREADED_PYTHON) target_compile_definitions(mcrogueface PRIVATE Py_DEBUG) endif() +# Enable Py_GIL_DISABLED for free-threaded CPython (no-GIL build) +if(MCRF_FREE_THREADED_PYTHON) + target_compile_definitions(mcrogueface PRIVATE Py_GIL_DISABLED) +endif() + # Define MCRF_HEADLESS for headless builds (excludes SFML/ImGui code) if(MCRF_HEADLESS) target_compile_definitions(mcrogueface PRIVATE MCRF_HEADLESS) diff --git a/Makefile b/Makefile index fd2b4fd..16f4d34 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ .PHONY: wasm wasm-game wasm-debug playground playground-debug serve serve-game serve-playground clean-wasm .PHONY: package-windows-light package-windows-full package-linux-light package-linux-full package-all .PHONY: version-bump -.PHONY: debug debug-test asan asan-test valgrind-test massif-test analyze clean-debug +.PHONY: debug debug-test asan asan-test tsan tsan-test valgrind-test massif-test analyze clean-debug # Number of parallel jobs for compilation JOBS := $(shell nproc 2>/dev/null || echo 4) @@ -114,6 +114,24 @@ asan-test: asan UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" \ python3 run_tests.py -v --sanitizer +tsan: + @echo "Building McRogueFace with TSan + free-threaded Python..." + @echo "NOTE: Requires free-threaded debug Python built with:" + @echo " tools/build_debug_python.sh --tsan" + @mkdir -p build-tsan + @cd build-tsan && cmake .. \ + -DCMAKE_BUILD_TYPE=Debug \ + -DMCRF_FREE_THREADED_PYTHON=ON \ + -DMCRF_SANITIZE_THREAD=ON && make -j$(JOBS) + @echo "TSan build complete! Output: build-tsan/mcrogueface" + +tsan-test: tsan + @echo "Running test suite under TSan..." + cd tests && MCRF_BUILD_DIR=../build-tsan \ + MCRF_LIB_DIR=../__lib_debug \ + TSAN_OPTIONS="halt_on_error=1:second_deadlock_stack=1" \ + python3 run_tests.py -v --sanitizer + valgrind-test: debug @echo "Running test suite under Valgrind memcheck..." cd tests && MCRF_BUILD_DIR=../build-debug \ @@ -151,7 +169,7 @@ analyze: clean-debug: @echo "Cleaning debug/sanitizer builds..." - @rm -rf build-debug build-asan + @rm -rf build-debug build-asan build-tsan # Packaging targets using tools/package.sh package-windows-light: windows