cmake_minimum_required(VERSION 3.27)

project(sentryward LANGUAGES CXX)
find_package(Threads REQUIRED)

set(SENTRYWARD_ASSUMPTION_DEFAULTS "${CMAKE_CURRENT_SOURCE_DIR}/config/default-assumptions.json")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SENTRYWARD_ASSUMPTION_DEFAULTS}")
file(READ "${SENTRYWARD_ASSUMPTION_DEFAULTS}" SENTRYWARD_ASSUMPTION_DEFAULTS_JSON)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/config/assumption-pool.json")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/config/assumption-pool.json" SENTRYWARD_ASSUMPTION_POOL_JSON)
configure_file(cpp/include/sentryward/algorithm/source_ir/default_assumptions.h.in
  generated/sentryward/algorithm/source_ir/default_assumptions.h @ONLY)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build configuration" FORCE)
endif()

option(SENTRYWARD_BUILD_TESTS "Build C++ correctness tests" ON)
option(SENTRYWARD_WARNINGS_AS_ERRORS "Treat C++ warnings as errors" ON)
option(SENTRYWARD_ENABLE_SANITIZERS "Enable address and undefined sanitizers" OFF)
option(SENTRYWARD_WITH_Z3 "Link Z3 for the symbolic address model's SMT layer" ON)
option(SENTRYWARD_ENABLE_COMPRESSION_AUDIT "Compile opt-in developer compression diagnostics" OFF)
if(SENTRYWARD_ENABLE_COMPRESSION_AUDIT)
  add_compile_definitions(SENTRYWARD_ENABLE_COMPRESSION_AUDIT)
endif()

add_library(sentryward_algorithm STATIC
  cpp/src/analysis/family_relation_query.cpp
  cpp/src/memory/family_access.cpp
  cpp/src/checker/family_memory_checker.cpp
  cpp/src/memory/family_conflict_order.cpp
  cpp/src/analysis/family_hb_reachability.cpp
  cpp/src/diagnostics/performance_profile.cpp
  cpp/src/diagnostics/memory_profile.cpp
  cpp/src/diagnostics/graph_memory_profile.cpp
  cpp/src/diagnostics/trace_memory_profile.cpp
  cpp/src/diagnostics/scoped_deadline.cpp
  cpp/src/source_ir/diagnostic.cpp
  cpp/src/source_ir/builder.cpp
  cpp/src/source_ir/initialization_recovery.cpp
  cpp/src/source_ir/ptx_assumptions.cpp
  cpp/src/source_ir/validator.cpp
  cpp/src/event_ir/dag.cpp
  cpp/src/event_ir/lowering.cpp
  cpp/src/event_ir/origin_map.cpp
  cpp/src/event_ir/program.cpp
  cpp/src/semantics/barrier_state.cpp
  cpp/src/semantics/collective_state.cpp
  cpp/src/semantics/reference_trace.cpp
  cpp/src/semantics/simulator.cpp
  cpp/src/solver/dinic.cpp
  cpp/src/solver/minimum_weight_ideal.cpp
  cpp/src/analysis/phase_database.cpp
  cpp/src/analysis/phase_algebra.cpp
  cpp/src/analysis/phase_boundary.cpp
  cpp/src/analysis/happens_before_graph.cpp
  cpp/src/analysis/trace_order.cpp
  cpp/src/analysis/reachability.cpp
  cpp/src/analysis/parallel_reachability.cpp
  cpp/src/analysis/shared_reachability_index.cpp
  cpp/src/analysis/hb_reachability.cpp
  cpp/src/analysis/compact_hb_reachability.cpp
  cpp/src/analysis/wait_checker.cpp
  cpp/src/analysis/wait_reachability_batch.cpp
  cpp/src/analysis/lifecycle_checker.cpp
  cpp/src/analysis/unordered_access_pairs.cpp
  cpp/src/memory/access.cpp
  cpp/src/memory/symbolic_address_model.cpp
  cpp/src/memory/constant_address_model.cpp
  cpp/src/memory/constant_address_candidates.cpp
  cpp/src/memory/conflict_order.cpp
  cpp/src/checker/wellsync_checker.cpp
  cpp/src/checker/memory_race_checker.cpp
  cpp/src/checker/duplicate_tma_stores.cpp
  cpp/src/checker/verifier.cpp
)
add_library(sentryward::algorithm ALIAS sentryward_algorithm)
target_link_libraries(sentryward_algorithm PUBLIC Threads::Threads)

# Layer 2 of the symbolic address model uses the Z3 C++ API. A matching-
# architecture z3-solver Python wheel also ships z3/include and z3/lib.
if(SENTRYWARD_WITH_Z3)
  find_path(SENTRYWARD_Z3_INCLUDE_DIR z3++.h
    HINTS ${CMAKE_CURRENT_SOURCE_DIR}/build/native-deps/z3/include)
  find_library(SENTRYWARD_Z3_LIBRARY NAMES z3 libz3
    HINTS ${CMAKE_CURRENT_SOURCE_DIR}/build/native-deps/z3/lib)
  if(NOT SENTRYWARD_Z3_INCLUDE_DIR OR NOT SENTRYWARD_Z3_LIBRARY)
    message(FATAL_ERROR "Z3 not found. Set SENTRYWARD_Z3_INCLUDE_DIR and SENTRYWARD_Z3_LIBRARY, "
      "or configure with -DSENTRYWARD_WITH_Z3=OFF (symbolic offsets then stay unresolved).")
  endif()
  target_sources(sentryward_algorithm PRIVATE cpp/src/memory/address_solver_z3.cpp)
  target_include_directories(sentryward_algorithm SYSTEM PRIVATE ${SENTRYWARD_Z3_INCLUDE_DIR})
  target_link_libraries(sentryward_algorithm PRIVATE ${SENTRYWARD_Z3_LIBRARY})
else()
  target_sources(sentryward_algorithm PRIVATE cpp/src/memory/address_solver_none.cpp)
endif()

target_include_directories(sentryward_algorithm
  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated
  PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/cpp/include
)
target_compile_features(sentryward_algorithm PUBLIC cxx_std_20)
target_include_directories(sentryward_algorithm SYSTEM PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)

if(MSVC)
  target_compile_options(sentryward_algorithm PRIVATE /W4)
  if(SENTRYWARD_WARNINGS_AS_ERRORS)
    target_compile_options(sentryward_algorithm PRIVATE /WX)
  endif()
else()
  target_compile_options(sentryward_algorithm PRIVATE
    -Wall
    -Wextra
    -Wpedantic
  )
  if(SENTRYWARD_WARNINGS_AS_ERRORS)
    target_compile_options(sentryward_algorithm PRIVATE -Werror)
  endif()
endif()

if(SENTRYWARD_ENABLE_SANITIZERS)
  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
    target_compile_options(sentryward_algorithm PUBLIC
      -fsanitize=address,undefined
      -fno-omit-frame-pointer
    )
    target_link_options(sentryward_algorithm PUBLIC
      -fsanitize=address,undefined
      -fno-omit-frame-pointer
    )
  else()
    message(FATAL_ERROR "SENTRYWARD_ENABLE_SANITIZERS requires Clang or GCC")
  endif()
endif()

add_library(sentryward_io STATIC cpp/src/io/source_json.cpp cpp/src/io/tmem_recovery.cpp
  cpp/src/io/source_storage.cpp
  cpp/src/diagnostics/source_memory_profile.cpp)
target_link_libraries(sentryward_io PUBLIC sentryward::algorithm)
target_compile_options(sentryward_io PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)
target_include_directories(sentryward_io SYSTEM PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
add_executable(sentryward-native cpp/src/cli/main.cpp)
add_executable(sentryward-conflicts cpp/src/diagnostics/conflict_review.cpp)
target_link_libraries(sentryward-conflicts PRIVATE sentryward_io)
target_include_directories(sentryward-conflicts SYSTEM PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
target_compile_options(sentryward-conflicts PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)
target_link_libraries(sentryward-native PRIVATE sentryward_io)
target_compile_options(sentryward-native PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)


if(SENTRYWARD_BUILD_TESTS)
  include(CTest)

  # Standalone header tests: check both compile-time erasure and opt-in behavior.
  foreach(mode enabled disabled)
    add_executable(sentryward_compression_audit_${mode}_test tests/cpp/diagnostics/compression_audit_test.cpp)
    target_include_directories(sentryward_compression_audit_${mode}_test PRIVATE cpp/include)
    target_compile_features(sentryward_compression_audit_${mode}_test PRIVATE cxx_std_20)
    if(mode STREQUAL "enabled")
      target_compile_definitions(sentryward_compression_audit_${mode}_test PRIVATE SENTRYWARD_ENABLE_COMPRESSION_AUDIT)
    else()
      target_compile_options(sentryward_compression_audit_${mode}_test PRIVATE
        $<$<CXX_COMPILER_ID:MSVC>:/USENTRYWARD_ENABLE_COMPRESSION_AUDIT>
        $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-USENTRYWARD_ENABLE_COMPRESSION_AUDIT>)
    endif()
    target_compile_options(sentryward_compression_audit_${mode}_test PRIVATE
      $<$<CXX_COMPILER_ID:MSVC>:/UNDEBUG>
      $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-UNDEBUG>)
    add_test(NAME sentryward_compression_audit_${mode}_test COMMAND sentryward_compression_audit_${mode}_test)
  endforeach()
  add_test(NAME sentryward_compression_audit_strict_test
    COMMAND ${CMAKE_COMMAND} -DPROGRAM=$<TARGET_FILE:sentryward_compression_audit_enabled_test>
      -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/cpp/diagnostics/compression_audit_strict.cmake)

  function(sentryward_add_cpp_test name source labels)
    add_executable(${name} ${source})
    target_link_libraries(${name} PRIVATE sentryward::algorithm)
    target_compile_features(${name} PRIVATE cxx_std_20)
    if(MSVC)
      target_compile_options(${name} PRIVATE /W4 /UNDEBUG)
      if(SENTRYWARD_WARNINGS_AS_ERRORS)
        target_compile_options(${name} PRIVATE /WX)
      endif()
    else()
      target_compile_options(${name} PRIVATE -Wall -Wextra -Wpedantic -UNDEBUG)
      if(SENTRYWARD_WARNINGS_AS_ERRORS)
        target_compile_options(${name} PRIVATE -Werror)
      endif()
    endif()
    add_test(NAME ${name} COMMAND ${name})
    set_tests_properties(${name} PROPERTIES LABELS "${labels}")
  endfunction()

  if(UNIX)
    sentryward_add_cpp_test(sentryward_scoped_deadline_test
      tests/cpp/diagnostics/scoped_deadline_test.cpp "unit;cpp;diagnostics")
  endif()

  sentryward_add_cpp_test(sentryward_base_checked_int_test
    tests/cpp/base/checked_int_test.cpp "unit;cpp;base")
  sentryward_add_cpp_test(sentryward_base_dynamic_bitset_test
    tests/cpp/base/dynamic_bitset_test.cpp "unit;cpp;base")
  sentryward_add_cpp_test(sentryward_base_result_test
    tests/cpp/base/result_test.cpp "unit;cpp;base")
  sentryward_add_cpp_test(sentryward_base_source_location_test
    tests/cpp/base/source_location_test.cpp "unit;cpp;base")
  sentryward_add_cpp_test(sentryward_base_shared_storage_test
    tests/cpp/base/shared_storage_test.cpp "unit;cpp;base")
  sentryward_add_cpp_test(sentryward_base_strong_id_test
    tests/cpp/base/strong_id_test.cpp "unit;cpp;base")

  sentryward_add_cpp_test(sentryward_source_ir_diagnostic_test
    tests/cpp/source_ir/diagnostic_test.cpp "unit;cpp;source_ir")
  sentryward_add_cpp_test(sentryward_source_ir_operation_test
    tests/cpp/source_ir/operation_test.cpp "unit;cpp;source_ir")
  sentryward_add_cpp_test(sentryward_source_ir_validator_test
    tests/cpp/source_ir/validator_test.cpp "unit;cpp;source_ir")
  sentryward_add_cpp_test(sentryward_source_ir_initialization_recovery_test
    tests/cpp/source_ir/initialization_recovery_test.cpp "unit;cpp;source_ir")
  sentryward_add_cpp_test(sentryward_ptx_assumptions_test
    tests/cpp/source_ir/ptx_assumptions_test.cpp "unit;cpp;source_ir")

  sentryward_add_cpp_test(sentryward_event_ir_dag_test
    tests/cpp/event_ir/dag_test.cpp "unit;cpp;event_ir")
  sentryward_add_cpp_test(sentryward_template_records_test
    tests/cpp/source_ir/template_records_test.cpp "unit;cpp;source_ir;event_ir")
  sentryward_add_cpp_test(sentryward_event_ir_lowering_test
    tests/cpp/event_ir/lowering_test.cpp "unit;cpp;event_ir")
  sentryward_add_cpp_test(sentryward_event_ir_origin_map_test
    tests/cpp/event_ir/origin_map_test.cpp "unit;cpp;event_ir")
  sentryward_add_cpp_test(sentryward_event_ir_program_test
    tests/cpp/event_ir/program_test.cpp "unit;cpp;event_ir")

  sentryward_add_cpp_test(sentryward_semantics_barrier_state_test
    tests/cpp/semantics/barrier_state_test.cpp "unit;cpp;semantics")
  sentryward_add_cpp_test(sentryward_semantics_collective_state_test
    tests/cpp/semantics/collective_state_test.cpp "unit;cpp;semantics")
  sentryward_add_cpp_test(sentryward_semantics_reference_trace_test
    tests/cpp/semantics/reference_trace_test.cpp "unit;cpp;semantics")
  sentryward_add_cpp_test(sentryward_semantics_simulator_test
    tests/cpp/semantics/simulator_test.cpp "unit;cpp;semantics")
  sentryward_add_cpp_test(sentryward_affine_template_schedule_test
    tests/cpp/semantics/affine_template_schedule_test.cpp "unit;cpp;semantics")

  sentryward_add_cpp_test(sentryward_solver_dinic_test
    tests/cpp/solver/dinic_test.cpp "unit;cpp;solver")
  sentryward_add_cpp_test(sentryward_solver_minimum_weight_ideal_test
    tests/cpp/solver/minimum_weight_ideal_test.cpp "unit;cpp;solver")

  sentryward_add_cpp_test(sentryward_lifecycle_checker_test
    tests/cpp/analysis/lifecycle_checker_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_phase_database_test
    tests/cpp/analysis/phase_database_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_phase_algebra_test
    tests/cpp/analysis/phase_algebra_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_phase_boundary_test
    tests/cpp/analysis/phase_boundary_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_phase_boundary_projection_test
    tests/cpp/analysis/phase_boundary_projection_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_happens_before_graph_test
    tests/cpp/analysis/happens_before_graph_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_trace_order_test tests/cpp/analysis/trace_order_test.cpp "unit;analysis")
  sentryward_add_cpp_test(sentryward_chain_frontier_test tests/cpp/analysis/chain_frontier_test.cpp "unit;analysis")
  sentryward_add_cpp_test(sentryward_ir_size_profile_test tests/cpp/diagnostics/ir_size_profile_test.cpp "unit;diagnostics")
  sentryward_add_cpp_test(sentryward_reachability_test
    tests/cpp/analysis/reachability_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_shared_reachability_index_test
    tests/cpp/analysis/shared_reachability_index_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_hb_reachability_test
    tests/cpp/analysis/hb_reachability_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_wait_checker_test
    tests/cpp/analysis/wait_checker_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_wait_reachability_batch_test
    tests/cpp/analysis/wait_reachability_batch_test.cpp "unit;cpp;analysis")

  sentryward_add_cpp_test(sentryward_wellsync_checker_test
    tests/cpp/checker/wellsync_checker_test.cpp "unit;cpp;checker")
  sentryward_add_cpp_test(sentryward_duplicate_tma_stores_test
    tests/cpp/checker/duplicate_tma_stores_test.cpp "unit;cpp;checker")

  sentryward_add_cpp_test(sentryward_memory_access_test
    tests/cpp/memory/access_test.cpp "unit;cpp;memory")
  sentryward_add_cpp_test(sentryward_memory_overlap_test
    tests/cpp/memory/overlap_test.cpp "unit;cpp;memory")
  sentryward_add_cpp_test(sentryward_constant_address_model_test
    tests/cpp/memory/constant_address_model_test.cpp "unit;cpp;memory")
  target_sources(sentryward_constant_address_model_test PRIVATE
    tests/cpp/memory/allocation_counter.cpp)
  sentryward_add_cpp_test(sentryward_symbolic_address_model_test
    tests/cpp/memory/symbolic_address_model_test.cpp "unit;cpp;memory")
  target_include_directories(sentryward_symbolic_address_model_test SYSTEM PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
  sentryward_add_cpp_test(sentryward_constant_address_candidates_test
    tests/cpp/memory/constant_address_candidates_test.cpp "unit;cpp;memory")
  sentryward_add_cpp_test(sentryward_unordered_access_pairs_test
    tests/cpp/analysis/unordered_access_pairs_test.cpp "unit;cpp;analysis")
  sentryward_add_cpp_test(sentryward_memory_race_checker_test
    tests/cpp/checker/memory_race_checker_test.cpp "unit;cpp;checker")
  sentryward_add_cpp_test(sentryward_family_memory_test
    tests/cpp/memory/family_memory_test.cpp "unit;cpp;memory")
  target_include_directories(sentryward_family_memory_test SYSTEM PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
  sentryward_add_cpp_test(sentryward_conflict_first_test
    tests/cpp/checker/conflict_first_test.cpp "unit;cpp;checker")
  sentryward_add_cpp_test(sentryward_verifier_test
    tests/cpp/checker/verifier_test.cpp "unit;cpp;checker")

  sentryward_add_cpp_test(sentryward_wellsync_checker_differential_test
    tests/end2end/checker/wellsync_checker_differential_test.cpp
    "end2end;cpp;checker")
  sentryward_add_cpp_test(sentryward_multi_producer_consumer_pipeline_test
    tests/end2end/checker/multi_producer_consumer_pipeline_test.cpp
    "end2end;cpp;checker")
  sentryward_add_cpp_test(sentryward_intra_warp_exchange_hb_test
    tests/end2end/checker/intra_warp_exchange_hb_test.cpp
    "end2end;cpp;checker")
  sentryward_add_cpp_test(sentryward_memory_race_verifier_test
    tests/end2end/checker/memory_race_verifier_test.cpp
    "end2end;cpp;checker")
  sentryward_add_cpp_test(sentryward_generic_async_test
    tests/end2end/checker/generic_async_test.cpp "end2end;cpp;checker")
  sentryward_add_cpp_test(sentryward_source_json_test
    tests/cpp/io/source_json_test.cpp "unit;cpp;io")
  set_property(TARGET sentryward_source_json_test PROPERTY LINK_LIBRARIES sentryward_io)
  sentryward_add_cpp_test(sentryward_tmem_recovery_test
    tests/cpp/io/tmem_recovery_test.cpp "unit;cpp;io")
  set_property(TARGET sentryward_tmem_recovery_test PROPERTY LINK_LIBRARIES sentryward_io)
endif()

add_library(sentryward_value_ir STATIC
  cpp/src/value_ir/type.cpp
  cpp/src/value_ir/operations.cpp
  cpp/src/value_ir/native_matrix.cpp
  cpp/src/value_ir/ptx_operation.cpp
  cpp/src/value_ir/graph.cpp
  cpp/src/value_ir/checkpoint_codec.cpp
  cpp/src/value_ir/printer.cpp)

# Debug checkpoints may survive downstream algorithm changes, never changes to
# the producer/checker/order boundary. Configure dependencies update this key on
# normal incremental builds, including dirty, uncommitted source changes.
file(GLOB_RECURSE _checkpoint_upstream CONFIGURE_DEPENDS
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/src/*.cpp"
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/src/*.h"
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/*.h"
  "${CMAKE_CURRENT_SOURCE_DIR}/config/*.json")
list(FILTER _checkpoint_upstream EXCLUDE REGEX "/(value_analysis|scalar_fold|equivalence|reference_guided)/")
list(APPEND _checkpoint_upstream
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/src/value_analysis/checkpoint.cpp"
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/sentryward/value_analysis/checkpoint.h"
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/sentryward/value_analysis/memory_actions.h"
  "${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/sentryward/value_analysis/memory_elimination.h")
list(SORT _checkpoint_upstream)
set(_checkpoint_key "v1;${CMAKE_CXX_COMPILER_ID};${CMAKE_CXX_COMPILER_VERSION};${CMAKE_CXX_FLAGS};${CMAKE_BUILD_TYPE};${SENTRYWARD_ENABLE_COMPRESSION_AUDIT};${SENTRYWARD_ENABLE_SANITIZERS}")
foreach(_checkpoint_file IN LISTS _checkpoint_upstream)
  set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_checkpoint_file}")
  file(SHA256 "${_checkpoint_file}" _checkpoint_sha)
  file(RELATIVE_PATH _checkpoint_relative "${CMAKE_CURRENT_SOURCE_DIR}" "${_checkpoint_file}")
  string(APPEND _checkpoint_key ";${_checkpoint_relative}:${_checkpoint_sha}")
endforeach()
string(SHA256 SENTRYWARD_CORRECTNESS_CACHE_UPSTREAM_KEY "${_checkpoint_key}")
configure_file(cpp/src/frontend/ptx/correctness_checkpoint_version.h.in
  generated/correctness_checkpoint_version.h @ONLY)
add_library(sentryward::value_ir ALIAS sentryward_value_ir)
target_include_directories(sentryward_value_ir PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cpp/include)
target_include_directories(sentryward_value_ir SYSTEM PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
target_compile_features(sentryward_value_ir PUBLIC cxx_std_20)
target_compile_options(sentryward_value_ir PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)
if(SENTRYWARD_ENABLE_SANITIZERS AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
  target_compile_options(sentryward_value_ir PUBLIC -fsanitize=address,undefined -fno-omit-frame-pointer)
  target_link_options(sentryward_value_ir PUBLIC -fsanitize=address,undefined -fno-omit-frame-pointer)
endif()

# PTX syntax/semantic decoding is independent of Python and graph verification.
add_library(sentryward_value_analysis STATIC
  cpp/src/scalar_fold/graph.cpp
  cpp/src/scalar_fold/artifact.cpp
  cpp/src/scalar_fold/consolidate_outputs.cpp
  cpp/src/scalar_fold/reduction_builder.cpp
  cpp/src/scalar_fold/real_expression_builder.cpp
  cpp/src/equivalence/egraph.cpp
  cpp/src/equivalence/constant_values.cpp
  cpp/src/equivalence/conversion_uses.cpp
  cpp/src/equivalence/output_mapping.cpp
  cpp/src/equivalence/input_mapping.cpp
  cpp/src/equivalence/packed_values.cpp
  cpp/src/equivalence/bit_origins.cpp
  cpp/src/equivalence/representation_rewriting.cpp
  cpp/src/equivalence/numerical_abstraction.cpp
  cpp/src/equivalence/numeric_semantics.cpp
  cpp/src/equivalence/math_intrinsics.cpp
  cpp/src/equivalence/polynomial_certificate.cpp
  cpp/src/equivalence/integer_interval.cpp
  cpp/src/equivalence/bounded_linear_reduction.cpp
  cpp/src/equivalence/finite_prefix_certificate.cpp
  cpp/src/equivalence/epoch_work_allowance.cpp
  cpp/src/equivalence/causal_region_certificate.cpp
  cpp/src/equivalence/bounded_index_translation.cpp
  cpp/src/equivalence/moment_certificate.cpp
  cpp/src/equivalence/comparison_context.cpp
  cpp/src/equivalence/lexical_scope.cpp
  cpp/src/equivalence/fold_rewriting.cpp
  cpp/src/equivalence/program.cpp
  cpp/src/equivalence/output_family.cpp
  cpp/src/equivalence/partitioned_outputs.cpp
  cpp/src/value_analysis/scalar_fold_lowering.cpp
  cpp/src/value_analysis/passes.cpp
  cpp/src/value_analysis/view_normalization.cpp
  cpp/src/value_analysis/indexed_source.cpp
  cpp/src/value_analysis/checkpoint.cpp
  cpp/src/value_analysis/memory_elimination.cpp
  cpp/src/value_analysis/printer.cpp)
add_library(sentryward::value_analysis ALIAS sentryward_value_analysis)
add_library(sentryward_reference_guided STATIC
  cpp/src/reference_guided/main.cpp cpp/src/reference_guided/production.cpp)
target_include_directories(sentryward_reference_guided PUBLIC cpp/src/reference_guided cpp/include)
target_include_directories(sentryward_reference_guided SYSTEM PUBLIC vendor/nlohmann_json/single_include)
target_link_libraries(sentryward_reference_guided PUBLIC sentryward::value_analysis)
add_executable(sentryward-equivalence cpp/src/reference_guided/cli.cpp cpp/src/reference_guided/file_runner.cpp)
target_link_libraries(sentryward-equivalence PRIVATE sentryward_reference_guided)
add_executable(sentryward-reference-guided-tests cpp/src/reference_guided/tests.cpp)
target_link_libraries(sentryward-reference-guided-tests PRIVATE sentryward_reference_guided)
add_test(NAME sentryward-reference-guided-tests COMMAND sentryward-reference-guided-tests)

target_link_libraries(sentryward_value_analysis PUBLIC sentryward::value_ir)
target_compile_options(sentryward_value_analysis PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)

add_library(sentryward_ptx STATIC
  cpp/src/frontend/ptx/parser.cpp
  cpp/src/frontend/ptx/semantics.cpp
  cpp/src/frontend/ptx/operands.cpp
  cpp/src/frontend/ptx/config.cpp
  cpp/src/frontend/ptx/public_input_parse.cpp
  cpp/src/frontend/ptx/public_input_normalize.cpp
  cpp/src/frontend/ptx/public_input_inference.cpp
  cpp/src/frontend/ptx/public_input_memory.cpp
  cpp/src/frontend/ptx/execution.cpp
  cpp/src/frontend/ptx/execution_records.cpp
  cpp/src/frontend/ptx/shared_execution.cpp
  cpp/src/frontend/ptx/named_phases.cpp
  cpp/src/frontend/ptx/tensor_maps.cpp
  cpp/src/frontend/ptx/layouts.cpp
  cpp/src/frontend/ptx/known_bits.cpp
  cpp/src/frontend/ptx/tmem_lifetime.cpp
  cpp/src/frontend/ptx/resources.cpp
  cpp/src/frontend/ptx/matrix.cpp
  cpp/src/frontend/ptx/refinement.cpp
  cpp/src/frontend/ptx/lowering.cpp
  cpp/src/frontend/ptx/source_dump.cpp
  cpp/src/frontend/ptx/value_ir.cpp
  cpp/src/frontend/ptx/branch_scope_capture.cpp
  cpp/src/frontend/ptx/readonly_origin.cpp
  cpp/src/frontend/ptx/rounded_sign.cpp
  cpp/src/frontend/ptx/certified_branch_scope.cpp
  cpp/src/frontend/ptx/address_expression.cpp
  cpp/src/frontend/ptx/semantic_program.cpp
  cpp/src/frontend/ptx/serialization.cpp
  cpp/src/frontend/ptx/selector_patterns.cpp
  cpp/src/frontend/ptx/group2_lifetime.cpp)
target_include_directories(sentryward_ptx PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cpp/include)
target_compile_features(sentryward_ptx PUBLIC cxx_std_20)
target_compile_options(sentryward_ptx PRIVATE $<TARGET_PROPERTY:sentryward_algorithm,COMPILE_OPTIONS>)
add_executable(sentryward-ptx-semantics cpp/src/frontend/ptx/main.cpp)
target_include_directories(sentryward-ptx-semantics SYSTEM PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
target_link_libraries(sentryward-ptx-semantics PRIVATE sentryward_ptx)

find_package(OpenSSL REQUIRED COMPONENTS Crypto)
find_path(SENTRYWARD_BOOST_INCLUDE_DIR boost/multiprecision/cpp_int.hpp
  HINTS ${CMAKE_CURRENT_SOURCE_DIR}/build/native-deps/boost/usr/include REQUIRED)
target_include_directories(sentryward_ptx SYSTEM PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include
  ${SENTRYWARD_BOOST_INCLUDE_DIR})
target_link_libraries(sentryward_ptx PUBLIC sentryward_io sentryward::value_ir OpenSSL::Crypto)
target_link_libraries(sentryward_value_analysis PUBLIC sentryward_ptx)
add_executable(sentryward-ptx cpp/src/frontend/ptx/run.cpp)
target_include_directories(sentryward-ptx PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated)
target_link_libraries(sentryward-ptx PRIVATE sentryward_ptx sentryward::value_analysis sentryward_reference_guided)

# Python wheels (scikit-build-core) carry the executables and configuration
# inside the package; sentryward/_paths.py resolves them there.
if(SKBUILD)
  install(TARGETS sentryward-ptx sentryward-native sentryward-conflicts
    RUNTIME DESTINATION sentryward/_native)
  install(FILES config/default-assumptions.json config/assumption-pool.json config/result-categories.json
    DESTINATION sentryward/_config)
endif()

if(SENTRYWARD_BUILD_TESTS)
  foreach(component type graph operations printer sharing parameterized_type native_matrix checkpoint)
    sentryward_add_cpp_test(sentryward_value_ir_${component}_test
      tests/cpp/value_ir/${component}_test.cpp "unit;cpp;value_ir")
    set_property(TARGET sentryward_value_ir_${component}_test PROPERTY LINK_LIBRARIES sentryward::value_ir)
  endforeach()
  target_include_directories(sentryward_value_ir_checkpoint_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cpp/src/value_ir)
  target_include_directories(sentryward_value_ir_checkpoint_test SYSTEM PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
  sentryward_add_cpp_test(sentryward_ptx_value_ir_test
    tests/cpp/frontend/ptx/value_ir_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_value_ir_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_branch_scope_capture_test
    tests/cpp/frontend/ptx/branch_scope_capture_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_branch_scope_capture_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_readonly_origin_test
    tests/cpp/frontend/ptx/readonly_origin_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_readonly_origin_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_rounded_sign_test
    tests/cpp/frontend/ptx/rounded_sign_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_rounded_sign_test PROPERTY LINK_LIBRARIES sentryward_ptx sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_ptx_certified_branch_scope_test
    tests/cpp/frontend/ptx/certified_branch_scope_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_certified_branch_scope_test PROPERTY LINK_LIBRARIES sentryward_ptx sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_ptx_address_expression_test
    tests/cpp/frontend/ptx/address_expression_test.cpp "unit;cpp;frontend;value_ir")
  set_property(TARGET sentryward_ptx_address_expression_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_semantic_program_test
    tests/cpp/frontend/ptx/semantic_program_test.cpp "unit;cpp;frontend;semantic_program")
  set_property(TARGET sentryward_ptx_semantic_program_test PROPERTY LINK_LIBRARIES sentryward_ptx sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_ptx_selector_patterns_test
    tests/cpp/frontend/ptx/selector_patterns_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_ptx_selector_patterns_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_shared_execution_test
    tests/cpp/frontend/ptx/shared_execution_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_ptx_shared_execution_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_ptx_matrix_elements_test
    tests/cpp/frontend/ptx/matrix_elements_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_ptx_matrix_elements_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  foreach(component memory_elimination printer passes type_edges view_normalization indexed_source scalar_fold_lowering checkpoint)
    sentryward_add_cpp_test(sentryward_value_analysis_${component}_test
      tests/cpp/value_analysis/${component}_test.cpp "unit;cpp;value_analysis")
    set_property(TARGET sentryward_value_analysis_${component}_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  endforeach()
  sentryward_add_cpp_test(sentryward_scalar_fold_graph_test
    tests/cpp/scalar_fold/graph_test.cpp "unit;cpp;scalar_fold")
  set_property(TARGET sentryward_scalar_fold_graph_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_scalar_fold_artifact_test
    tests/cpp/scalar_fold/artifact_test.cpp "unit;cpp;scalar_fold")
  set_property(TARGET sentryward_scalar_fold_artifact_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_scalar_fold_reduction_builder_test
    tests/cpp/scalar_fold/reduction_builder_test.cpp "unit;cpp;scalar_fold")
  set_property(TARGET sentryward_scalar_fold_reduction_builder_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_scalar_fold_real_expression_builder_test
    tests/cpp/scalar_fold/real_expression_builder_test.cpp "unit;cpp;scalar_fold")
  set_property(TARGET sentryward_scalar_fold_real_expression_builder_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_constant_values_test
    tests/cpp/equivalence/constant_values_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_constant_values_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_comparison_context_test
    tests/cpp/equivalence/comparison_context_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_comparison_context_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_u64_add_test
    tests/cpp/equivalence/egraph_u64_add_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_u64_add_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_lexical_scope_test
    tests/cpp/equivalence/lexical_scope_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_lexical_scope_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_scoped_saturation_test
    tests/cpp/equivalence/egraph_scoped_saturation_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_scoped_saturation_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_subtractive_exponential_offset_test
    tests/cpp/equivalence/egraph_subtractive_exponential_offset_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_subtractive_exponential_offset_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_test
    tests/cpp/equivalence/egraph_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  foreach(component output_family partitioned_outputs program_family)
    sentryward_add_cpp_test(sentryward_equivalence_${component}_test
      tests/cpp/equivalence/${component}_test.cpp "unit;cpp;equivalence")
    set_property(TARGET sentryward_equivalence_${component}_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  endforeach()
  foreach(component consolidate_outputs artifact_family)
    sentryward_add_cpp_test(sentryward_scalar_fold_${component}_test
      tests/cpp/scalar_fold/${component}_test.cpp "unit;cpp;scalar_fold")
    set_property(TARGET sentryward_scalar_fold_${component}_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  endforeach()
  sentryward_add_cpp_test(sentryward_value_analysis_output_family_lowering_test
    tests/cpp/value_analysis/output_family_lowering_test.cpp "unit;cpp;value_analysis")
  set_property(TARGET sentryward_value_analysis_output_family_lowering_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_event_ir_generated_lowering_test
    tests/cpp/event_ir/generated_lowering_test.cpp "unit;cpp;event_ir")
  sentryward_add_cpp_test(sentryward_event_ir_event_order_test
    tests/cpp/event_ir/event_order_test.cpp "unit;cpp;event_ir")
  sentryward_add_cpp_test(sentryward_equivalence_output_mapping_test
    tests/cpp/equivalence/output_mapping_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_output_mapping_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_input_mapping_test
    tests/cpp/equivalence/input_mapping_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_input_mapping_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_numerical_abstraction_test
    tests/cpp/equivalence/numerical_abstraction_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_numerical_abstraction_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_numeric_semantics_test
    tests/cpp/equivalence/numeric_semantics_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_numeric_semantics_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_numerical_vocabulary_test
    tests/cpp/equivalence/numerical_vocabulary_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_numerical_vocabulary_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_math_intrinsics_test
    tests/cpp/equivalence/math_intrinsics_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_math_intrinsics_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_polynomial_certificate_test
    tests/cpp/equivalence/polynomial_certificate_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_polynomial_certificate_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_integer_interval_test
    tests/cpp/equivalence/integer_interval_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_integer_interval_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_rectangular_test
    tests/cpp/equivalence/egraph_rectangular_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_rectangular_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_bounded_linear_reduction_test
    tests/cpp/equivalence/bounded_linear_reduction_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_bounded_linear_reduction_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_linear_reduction_test
    tests/cpp/equivalence/egraph_linear_reduction_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_linear_reduction_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_scoped_sum_test
    tests/cpp/equivalence/egraph_scoped_sum_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_scoped_sum_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_scoped_sum_inactive_axis_test
    tests/cpp/equivalence/egraph_scoped_sum_inactive_axis_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_scoped_sum_inactive_axis_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_scoped_sum_completed_rebind_test
    tests/cpp/equivalence/egraph_scoped_sum_completed_rebind_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_scoped_sum_completed_rebind_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_scoped_work_budget_test
    tests/cpp/equivalence/scoped_work_budget_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_scoped_work_budget_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_moment_certificate_test
    tests/cpp/equivalence/moment_certificate_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_moment_certificate_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_finite_prefix_certificate_test
    tests/cpp/equivalence/finite_prefix_certificate_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_finite_prefix_certificate_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_epoch_work_allowance_test
    tests/cpp/equivalence/epoch_work_allowance_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_epoch_work_allowance_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_finite_prefix_output_test
    tests/cpp/equivalence/egraph_finite_prefix_output_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_finite_prefix_output_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_scoped_body_relation_test
    tests/cpp/equivalence/scoped_body_relation_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_scoped_body_relation_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_work_charge_test
    tests/cpp/equivalence/work_charge_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_work_charge_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_joined_body_relation_test
    tests/cpp/equivalence/joined_body_relation_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_joined_body_relation_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_causal_region_certificate_test
    tests/cpp/equivalence/causal_region_certificate_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_causal_region_certificate_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_scoped_product_relation_test
    tests/cpp/equivalence/scoped_product_relation_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_scoped_product_relation_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_coverage_residual_test
    tests/cpp/equivalence/egraph_coverage_residual_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_coverage_residual_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_bounded_index_translation_test
    tests/cpp/equivalence/bounded_index_translation_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_bounded_index_translation_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_closed_factor_coverage_test
    tests/cpp/equivalence/egraph_closed_factor_coverage_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_closed_factor_coverage_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_constant_head_filter_test
    tests/cpp/equivalence/egraph_constant_head_filter_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_constant_head_filter_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_egraph_import_fold_match_test
    tests/cpp/equivalence/egraph_import_fold_match_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_egraph_import_fold_match_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_output_family_cohort_test
    tests/cpp/equivalence/output_family_cohort_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_output_family_cohort_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_representation_rewriting_test
    tests/cpp/equivalence/representation_rewriting_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_representation_rewriting_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_fold_rewriting_test
    tests/cpp/equivalence/fold_rewriting_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_fold_rewriting_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_equivalence_program_test
    tests/cpp/equivalence/program_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_program_test PROPERTY LINK_LIBRARIES sentryward::value_analysis)
  sentryward_add_cpp_test(sentryward_memory_profile_test
    tests/cpp/diagnostics/memory_profile_test.cpp "unit;cpp;diagnostics")
  target_include_directories(sentryward_memory_profile_test SYSTEM PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/single_include)
  sentryward_add_cpp_test(sentryward_dependency_history_test
    tests/cpp/frontend/ptx/dependency_history_test.cpp "unit;cpp;frontend")
  sentryward_add_cpp_test(sentryward_refinement_prefix_test
    tests/frontend_native/refinement_prefix_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_refinement_prefix_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_public_input_test
    tests/cpp/frontend/ptx/public_input_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_public_input_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_execution_records_test
    tests/cpp/frontend/ptx/execution_records_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_execution_records_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_thread_compression_test
    tests/cpp/frontend/ptx/thread_compression_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_thread_compression_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_frontend_migration_test
    tests/cpp/frontend/ptx/migration_regression_test.cpp "unit;cpp;frontend")
  set_property(TARGET sentryward_frontend_migration_test PROPERTY LINK_LIBRARIES sentryward_ptx)
  sentryward_add_cpp_test(sentryward_equivalence_stored_class_catalog_test
    tests/cpp/equivalence/stored_class_catalog_test.cpp "unit;cpp;equivalence")
  set_property(TARGET sentryward_equivalence_stored_class_catalog_test
    PROPERTY LINK_LIBRARIES sentryward::value_analysis)
endif()

target_include_directories(sentryward-native SYSTEM PRIVATE vendor/nlohmann_json/single_include)

if(SENTRYWARD_BUILD_TESTS)
  sentryward_add_cpp_test(sentryward_result_contract_test tests/cpp/result_contract_test.cpp "unit;cpp;result")
  target_include_directories(sentryward_result_contract_test SYSTEM PRIVATE vendor/nlohmann_json/single_include)
endif()
