cmake_minimum_required(VERSION 3.18) set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) set(EXECUTABLE_NAME fallout2-ce) if(APPLE) if(IOS) set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "") set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "") else() set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "") set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "") endif() endif() project(${EXECUTABLE_NAME}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) if(MSVC) add_compile_options($<$:/EHsc>) endif() option(FALLOUT_VENDORED "Use vendored third-party libraries" ON) option(FALLOUT_AUDIO_OGG "Enable OGG decoding with stb_vorbis when available" ON) set(FALLOUT_STB_VORBIS_DIR "" CACHE PATH "Directory containing stb_vorbis.c") if(ANDROID) add_library(${EXECUTABLE_NAME} SHARED) else() add_executable(${EXECUTABLE_NAME} WIN32 MACOSX_BUNDLE) endif() # Git Info include("cmake/gitver.cmake") # Shared engine sources — used by both game and mapper targets. # Excludes main.cc/main.h (game-only entry logic). set(FALLOUT_ENGINE_SOURCES "src/actions.cc" "src/actions.h" "src/animation.cc" "src/animation.h" "src/art.cc" "src/art.h" "src/audio.cc" "src/audio.h" "src/automap.cc" "src/automap.h" "src/autorun.cc" "src/autorun.h" "src/cache.cc" "src/cache.h" "src/character_editor.cc" "src/character_editor.h" "src/character_selector.cc" "src/character_selector.h" "src/color.cc" "src/color.h" "src/combat_ai_defs.h" "src/combat_ai.cc" "src/combat_ai.h" "src/combat_defs.h" "src/combat.cc" "src/combat.h" "src/config.cc" "src/config.h" "src/content_config.cc" "src/content_config.h" "src/credits.cc" "src/credits.h" "src/critter.cc" "src/critter.h" "src/cycle.cc" "src/cycle.h" "src/datafile.cc" "src/datafile.h" "src/db.cc" "src/db.h" "src/dbox.cc" "src/dbox.h" "src/debug.cc" "src/debug.h" "src/dfile.cc" "src/dfile.h" "src/dialog.cc" "src/dialog.h" "src/dictionary.cc" "src/dictionary.h" "src/dinput.cc" "src/dinput.h" "src/display_monitor.cc" "src/display_monitor.h" "src/draw.cc" "src/draw.h" "src/elevator.cc" "src/elevator.h" "src/endgame.cc" "src/endgame.h" "src/export.cc" "src/export.h" "src/file_find.cc" "src/file_find.h" "src/file_utils.cc" "src/file_utils.h" "src/font_manager.cc" "src/font_manager.h" "src/game_config.cc" "src/game_config.h" "src/game_config_migration.cc" "src/game_config_migration.h" "src/game_dialog.cc" "src/game_dialog.h" "src/game_memory.cc" "src/game_memory.h" "src/game_mouse.cc" "src/game_mouse.h" "src/game_movie.cc" "src/game_movie.h" "src/game_sound.cc" "src/game_sound.h" "src/game_vars.h" "src/game.cc" "src/game.h" "src/geometry.cc" "src/geometry.h" "src/graph_lib.cc" "src/graph_lib.h" "src/heap.cc" "src/heap.h" "src/input.cc" "src/input.h" "src/interface.cc" "src/interface.h" "src/interpreter_extra.cc" "src/interpreter_extra.h" "src/interpreter_lib.cc" "src/interpreter_lib.h" "src/interpreter.cc" "src/interpreter.h" "src/inventory.cc" "src/inventory.h" "src/item.cc" "src/item.h" "src/kb.cc" "src/kb.h" "src/light.cc" "src/light.h" "src/lips.cc" "src/lips.h" "src/loadsave.cc" "src/loadsave.h" "src/mainmenu.cc" "src/mainmenu.h" "src/map_defs.h" "src/map.cc" "src/map.h" "src/map_edge.cc" "src/map_edge.h" "src/memory_defs.h" "src/memory_manager.cc" "src/memory_manager.h" "src/memory.cc" "src/memory.h" "src/message.cc" "src/message.h" "src/mouse_manager.cc" "src/mouse_manager.h" "src/mouse.cc" "src/mouse.h" "src/movie_effect.cc" "src/movie_effect.h" "src/movie_lib.cc" "src/movie_lib.h" "src/movie.cc" "src/movie.h" "src/nevs.cc" "src/nevs.h" "src/obj_types.h" "src/object.cc" "src/object.h" "src/ogg_decoder.cc" "src/ogg_decoder.h" "src/opcode_context.cc" "src/opcode_context.h" "src/options.cc" "src/options.h" "src/palette.cc" "src/palette.h" "src/party_member.cc" "src/party_member.h" "src/pcx.cc" "src/pcx.h" "src/perk_defs.h" "src/perk.cc" "src/perk.h" "src/pipboy.cc" "src/pipboy.h" "src/proto_instance.cc" "src/proto_instance.h" "src/proto_types.h" "src/proto.cc" "src/proto.h" "src/queue.cc" "src/queue.h" "src/random.cc" "src/random.h" "src/reaction.cc" "src/reaction.h" "src/region.cc" "src/region.h" "src/scripts.cc" "src/scripts.h" "src/select_file_list.cc" "src/select_file_list.h" "src/skill_defs.h" "src/skill.cc" "src/skill.h" "src/skilldex.cc" "src/skilldex.h" "src/sound_decoder.cc" "src/sound_decoder.h" "src/sound_effects_cache.cc" "src/sound_effects_cache.h" "src/sound_effects_list.cc" "src/sound_effects_list.h" "src/sound.cc" "src/sound.h" "src/stat_defs.h" "src/stat.cc" "src/stat.h" "src/string_parsers.cc" "src/string_parsers.h" "src/svga.cc" "src/svga.h" "src/text_font.cc" "src/text_font.h" "src/text_object.cc" "src/text_object.h" "src/tile.cc" "src/tile.h" "src/tile_hires_stencil.cc" "src/tile_hires_stencil.h" "src/trait_defs.h" "src/trait.cc" "src/trait.h" "src/version.cc" "src/version.h" "src/widget.cc" "src/widget.h" "src/win32.cc" "src/win32.h" "src/window_manager_private.cc" "src/window_manager_private.h" "src/window_manager.cc" "src/window_manager.h" "src/window.cc" "src/window.h" "src/word_wrap.cc" "src/word_wrap.h" "src/worldmap.cc" "src/worldmap.h" "src/xfile.cc" "src/xfile.h" ) set(FALLOUT_PLATFORM_SOURCES "src/audio_engine.cc" "src/audio_engine.h" "src/delay.cc" "src/delay.h" "src/fps_limiter.cc" "src/fps_limiter.h" "src/platform_compat.cc" "src/platform_compat.h" "src/pointer_registry.cc" "src/pointer_registry.h" "src/preferences.cc" "src/preferences.h" "src/settings.cc" "src/settings.h" "src/sfall_config.cc" "src/sfall_config.h" "src/sfall_ext.cc" "src/sfall_ext.h" "src/sfall_global_vars.cc" "src/sfall_global_vars.h" "src/sfall_global_scripts.cc" "src/sfall_global_scripts.h" "src/sfall_ini.cc" "src/sfall_ini.h" "src/sfall_kb_helpers.cc" "src/sfall_kb_helpers.h" "src/sfall_lists.cc" "src/sfall_lists.h" "src/sfall_metarules.cc" "src/sfall_metarules.h" "src/sfall_opcodes.cc" "src/sfall_opcodes.h" "src/sfall_script_hooks.cc" "src/script_sound.cc" "src/script_sound.h" "src/sfall_arrays.cc" "src/sfall_arrays.h" "src/sfall_animation.cc" "src/sfall_animation.h" "src/sfall_callbacks.cc" "src/sfall_callbacks.h" "src/touch.cc" "src/touch.h" "src/scan_unimplemented.cc" "third_party/lodepng/lodepng.cpp" ) target_sources(${EXECUTABLE_NAME} PUBLIC ${FALLOUT_ENGINE_SOURCES} "src/main.cc" "src/main.h" ) target_sources(${EXECUTABLE_NAME} PUBLIC ${FALLOUT_PLATFORM_SOURCES}) target_include_directories(${EXECUTABLE_NAME} PUBLIC "third_party/lodepng") set(FALLOUT_HAVE_STB_VORBIS OFF) if(FALLOUT_AUDIO_OGG) if(EXISTS "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis/stb_vorbis.c") set(_fallout_stb_vorbis_dir "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis") else() set(_fallout_stb_vorbis_dir "${FALLOUT_STB_VORBIS_DIR}") if(NOT _fallout_stb_vorbis_dir) find_path(_fallout_stb_vorbis_dir NAMES "stb_vorbis.c" DOC "Directory containing stb_vorbis.c") endif() endif() if(_fallout_stb_vorbis_dir AND EXISTS "${_fallout_stb_vorbis_dir}/stb_vorbis.c") set(FALLOUT_HAVE_STB_VORBIS ON) target_include_directories(${EXECUTABLE_NAME} PRIVATE "${_fallout_stb_vorbis_dir}") else() message(STATUS "OGG support disabled: stb_vorbis.c not found") endif() endif() if(FALLOUT_HAVE_STB_VORBIS) target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=1) else() target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=0) endif() if(IOS) target_sources(${EXECUTABLE_NAME} PUBLIC "src/platform/ios/paths.h" "src/platform/ios/paths.mm" "src/platform/ios/quick_toolbar.h" "src/platform/ios/quick_toolbar.cc" ) endif() if(WIN32) target_compile_definitions(${EXECUTABLE_NAME} PUBLIC _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN _STATIC_CPPLIB ) endif() if(MINGW) target_compile_definitions(${EXECUTABLE_NAME} PUBLIC _USE_MATH_DEFINES ) endif() if(WIN32) target_link_libraries(${EXECUTABLE_NAME} winmm ) endif() if(MSVC) target_link_libraries(${EXECUTABLE_NAME} debug libcpmtd optimized libcpmt ) endif() if(MINGW) target_link_options(${EXECUTABLE_NAME} PRIVATE -static -static-libgcc -static-libstdc++ ) endif() if(WIN32) target_sources(${EXECUTABLE_NAME} PUBLIC "os/windows/fallout2-ce.ico" "os/windows/fallout2-ce.rc" ) endif() if(APPLE) if(IOS) set(RESOURCES "os/ios/AppIcon.xcassets" "os/ios/LaunchScreen.storyboard" ) target_sources(${EXECUTABLE_NAME} PUBLIC ${RESOURCES}) set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_target_properties(${EXECUTABLE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/os/ios/Info.plist" XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.alexbatalov.fallout2-ce" XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" ) set(MACOSX_BUNDLE_BUNDLE_NAME "${EXECUTABLE_NAME}") set(MACOSX_BUNDLE_DISPLAY_NAME "Fallout 2") else() set(RESOURCES "os/macos/fallout2-ce.icns" ) target_link_libraries(${EXECUTABLE_NAME} "-framework CoreFoundation") target_sources(${EXECUTABLE_NAME} PUBLIC ${RESOURCES}) set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME "Fallout II Community Edition" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/os/macos/Info.plist" XCODE_ATTRIBUTE_EXECUTABLE_NAME "${EXECUTABLE_NAME}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.alexbatalov.fallout2-ce" ) set(MACOSX_BUNDLE_ICON_FILE "fallout2-ce.icns") set(MACOSX_BUNDLE_BUNDLE_NAME "Fallout II: Community Edition") set(MACOSX_BUNDLE_DISPLAY_NAME "Fallout II") endif() set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.alexbatalov.fallout2-ce") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "1.3.0") set(MACOSX_BUNDLE_BUNDLE_VERSION "1.3.0") endif() if((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")) if(FALLOUT_VENDORED) add_subdirectory("third_party/zlib") add_subdirectory("third_party/sdl2") else() find_package(ZLIB) find_package(SDL2) endif() else() set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ --use-port=sdl2 \ --use-port=sdl2_mixer \ --use-port=zlib" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ --use-port=sdl2 \ --use-port=sdl2_mixer \ --use-port=zlib \ -std=c++17" ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O1") set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1") if(OPTION_WASM_64) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sMEMORY64" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sMEMORY64" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sMEMORY64" ) add_compile_options( -sMEMORY64 ) endif() if(OPTION_WASM_JSPI) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sJSPI" ) else() target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sASYNCIFY" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sASYNCIFY_STACK_SIZE=20480" ) endif() target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sENVIRONMENT=web" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sALLOW_MEMORY_GROWTH" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-MEMORY_GROWTH_LINEAR_STEP=32mb" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sNO_DISABLE_EXCEPTION_CATCHING" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-lidbfs.js" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sCASE_INSENSITIVE_FS" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sMODULARIZE" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sEXPORTED_RUNTIME_METHODS=callMain,addRunDependency,removeRunDependency" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sEXPORT_ALL" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sEXPORT_NAME=fallout2ce" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "-sEXIT_RUNTIME" ) target_link_options( ${EXECUTABLE_NAME} PRIVATE "$<$:-g>" ) endif() add_subdirectory("third_party/fpattern") target_link_libraries(${EXECUTABLE_NAME} fpattern::fpattern) target_link_libraries(${EXECUTABLE_NAME} fpattern_windows::fpattern_windows) target_link_libraries(${EXECUTABLE_NAME} ${ZLIB_LIBRARIES}) target_include_directories(${EXECUTABLE_NAME} PRIVATE ${ZLIB_INCLUDE_DIRS}) target_link_libraries(${EXECUTABLE_NAME} ${SDL2_LIBRARIES}) target_link_libraries(${EXECUTABLE_NAME} ${SDL2_MAIN_LIBRARIES}) target_include_directories(${EXECUTABLE_NAME} PRIVATE ${SDL2_INCLUDE_DIRS}) if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")) add_executable(ce-dat-tool "tools/dat_tool.cc" "tools/dat_archive.cc" "tools/fo1_dat_lzss.cc" "src/dfile.cc" "src/platform_compat.cc" ) if(APPLE) set_target_properties(ce-dat-tool PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" ) endif() target_link_libraries(ce-dat-tool fpattern_windows::fpattern_windows ${ZLIB_LIBRARIES} ${SDL2_LIBRARIES} ) if(WIN32) target_link_libraries(ce-dat-tool winmm) endif() if(MINGW) target_link_options(ce-dat-tool PRIVATE -static -static-libgcc -static-libstdc++ ) endif() target_include_directories(ce-dat-tool PRIVATE "src") target_include_directories(ce-dat-tool PRIVATE ${ZLIB_INCLUDE_DIRS}) target_include_directories(ce-dat-tool PRIVATE ${SDL2_INCLUDE_DIRS}) add_executable(ce-frm2png "tools/ce_frm2png.cc" "src/platform_compat.cc" "third_party/lodepng/lodepng.cpp" ) if(APPLE) set_target_properties(ce-frm2png PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" ) endif() target_include_directories(ce-frm2png PRIVATE "src") target_include_directories(ce-frm2png PRIVATE "third_party/lodepng") target_include_directories(ce-frm2png PRIVATE ${SDL2_INCLUDE_DIRS}) target_include_directories(ce-frm2png PRIVATE ${ZLIB_INCLUDE_DIRS}) target_link_libraries(ce-frm2png ${SDL2_LIBRARIES}) target_link_libraries(ce-frm2png ${ZLIB_LIBRARIES}) if(MINGW) target_link_options(ce-frm2png PRIVATE -static -static-libgcc -static-libstdc++ ) endif() if(APPLE) file(GLOB_RECURSE CE_DAT_INPUTS CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/files/ce.dat/*") set(CE_DAT_RESOURCE_PATH "${CMAKE_CURRENT_BINARY_DIR}/ce.dat") add_custom_command( OUTPUT "${CE_DAT_RESOURCE_PATH}" COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}" COMMAND $ create "${CMAKE_SOURCE_DIR}/files/ce.dat" "${CE_DAT_RESOURCE_PATH}" DEPENDS ce-dat-tool ${CE_DAT_INPUTS} COMMENT "Generating ce.dat for app bundle" VERBATIM ) add_custom_target(ce-dat-resource DEPENDS "${CE_DAT_RESOURCE_PATH}") add_dependencies(${EXECUTABLE_NAME} ce-dat-resource) target_sources(${EXECUTABLE_NAME} PRIVATE "${CE_DAT_RESOURCE_PATH}") set_source_files_properties("${CE_DAT_RESOURCE_PATH}" PROPERTIES GENERATED TRUE MACOSX_PACKAGE_LOCATION "Resources") endif() endif() if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")) if(WIN32) add_executable(mapper-ce WIN32) else() add_executable(mapper-ce) endif() target_sources(mapper-ce PUBLIC ${FALLOUT_ENGINE_SOURCES} ${FALLOUT_PLATFORM_SOURCES} "src/mapper/map_edge_setup.cc" "src/mapper/map_edge_setup.h" "src/mapper/map_func.cc" "src/mapper/map_func.h" "src/mapper/mapper.cc" "src/mapper/mapper.h" "src/mapper/mp_instance.cc" "src/mapper/mp_instance.h" "src/mapper/mp_proto.cc" "src/mapper/mp_proto.h" "src/mapper/mp_scrpt.cc" "src/mapper/mp_scrpt.h" "src/mapper/mp_targt.cc" "src/mapper/mp_targt.h" "src/mapper/mp_utils.cc" "src/mapper/mp_utils.h" "src/mapper/mp_text.cc" "src/mapper/mp_text.h" ) target_compile_definitions(mapper-ce PUBLIC FALLOUT_MAPPER) if(WIN32) target_compile_definitions(mapper-ce PUBLIC _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN _STATIC_CPPLIB ) if(MINGW) target_compile_definitions(mapper-ce PUBLIC _USE_MATH_DEFINES ) target_link_options(mapper-ce PRIVATE -static -static-libgcc -static-libstdc++ ) endif() target_link_libraries(mapper-ce winmm ) if(MSVC) target_link_libraries(mapper-ce debug libcpmtd optimized libcpmt ) endif() target_sources(mapper-ce PUBLIC "os/windows/fallout2-ce.rc" ) endif() if(APPLE) target_link_libraries(mapper-ce "-framework CoreFoundation") set_target_properties(mapper-ce PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO" ) endif() target_include_directories(mapper-ce PUBLIC "third_party/lodepng") target_include_directories(mapper-ce PRIVATE "src") target_include_directories(mapper-ce PRIVATE ${ZLIB_INCLUDE_DIRS}) target_include_directories(mapper-ce PRIVATE ${SDL2_INCLUDE_DIRS}) target_link_libraries(mapper-ce fpattern::fpattern fpattern_windows::fpattern_windows ${ZLIB_LIBRARIES} ${SDL2_LIBRARIES} ${SDL2_MAIN_LIBRARIES} ) endif() if(APPLE) if(IOS) install(TARGETS ${EXECUTABLE_NAME} DESTINATION "Payload") set(CPACK_GENERATOR "ZIP") set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) set(CPACK_PACKAGE_FILE_NAME "fallout2-ce") set(CPACK_ARCHIVE_FILE_EXTENSION "ipa") else() install(TARGETS ${EXECUTABLE_NAME} DESTINATION .) set(CPACK_GENERATOR "DragNDrop") set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK ON) set(CPACK_PACKAGE_FILE_NAME "Fallout II Community Edition") endif() include(CPack) endif() # Add option to enable AddressSanitizer option(ENABLE_ASAN "Enable AddressSanitizer for debug builds" OFF) # Set C++ standard and other existing settings set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) # Define ASan flags for supported compilers (GCC, Clang, MSVC) if(ENABLE_ASAN) if(CMAKE_SYSTEM_NAME MATCHES "Emscripten|Android|iOS") message(WARNING "AddressSanitizer is not supported on ${CMAKE_SYSTEM_NAME}. Disabling ASan.") set(ENABLE_ASAN OFF) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") message(STATUS "Enabling AddressSanitizer for debug build (GCC/Clang)") set(ASAN_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${ASAN_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${ASAN_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${ASAN_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${ASAN_FLAGS}") elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") # Check if using clang-cl or native MSVC if(CMAKE_CXX_COMPILER MATCHES "clang-cl") message(STATUS "Enabling AddressSanitizer for debug build (clang-cl)") set(ASAN_FLAGS "-fsanitize=address -fno-omit-frame-pointer") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${ASAN_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${ASAN_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fsanitize=address") set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address") else() message(STATUS "Enabling AddressSanitizer for debug build (MSVC)") set(ASAN_FLAGS "/fsanitize=address") # MSVC requires /Zi or /Z7 for debug info with ASan set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${ASAN_FLAGS} /Zi") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${ASAN_FLAGS} /Zi") # No additional linker flags needed for MSVC ASan # Disable incremental linking as it's incompatible with ASan string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") endif() else() message(WARNING "AddressSanitizer is not supported with ${CMAKE_CXX_COMPILER_ID}. Disabling ASan.") set(ENABLE_ASAN OFF) endif() endif() # Existing debug flags for Emscripten (ensure ASan doesn't conflict) if(CMAKE_SYSTEM_NAME MATCHES "Emscripten") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") endif()