# Builds the unchanged robot firmware (robot/) into a PC library for the
# Unity simulation, against the hardware stand-ins in shim/.
#
#   cmake -S sim -B sim/build -G Ninja -DCMAKE_BUILD_TYPE=Release
#   cmake --build sim/build
#   sim/build/sim_smoke.exe          headless smoke test
#
# Output: sim/build/hexapod_sim.dll (Unity loads it from there; see sim/README.md).
cmake_minimum_required(VERSION 3.16)
project(hexapod_sim CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

set(REPO_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
file(GLOB ROBOT_SOURCES CONFIGURE_DEPENDS ${REPO_ROOT}/robot/*.cpp)

# Each robot/*.cpp is compiled through a one-line wrapper in the build dir.
# Compiling it in place would make robot/ the main source directory, and on
# Windows' case-insensitive filesystem GCC's own <limits.h> chain
# (syslimits.h -> #include_next) then picks up robot/Limits.h.
set(ROBOT_WRAPPERS)
foreach(src ${ROBOT_SOURCES})
  get_filename_component(name ${src} NAME_WE)
  set(wrapper ${CMAKE_CURRENT_BINARY_DIR}/robot_src/${name}.cpp)
  file(CONFIGURE OUTPUT ${wrapper} CONTENT "// generated by sim/CMakeLists.txt\n#include \"${src}\"\n")
  list(APPEND ROBOT_WRAPPERS ${wrapper})
endforeach()

# Everything shared by the DLL and the test exe (robot.ino via robot_ino.cpp).
add_library(robot_core OBJECT
  ${ROBOT_WRAPPERS}
  robot_ino.cpp
  SimHardware.cpp
  SimBody.cpp
  HexapodSimApi.cpp
)
# shim/ first so <Arduino.h>, <Servo.h>, <RF24.h>... resolve to the stand-ins.
target_include_directories(robot_core PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/shim
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${REPO_ROOT}/shared/HexapodProtocol
)# robot/ is deliberately NOT an include directory (not even -iquote: GCC's
# #include_next searches those too). Sim sources include "../robot/..." directly.
target_compile_definitions(robot_core PUBLIC HEXAPOD_SIM=1)
set_target_properties(robot_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
  target_compile_options(robot_core PRIVATE -Wall -Wextra -Wno-unused-parameter)
endif()
set_source_files_properties(robot_ino.cpp PROPERTIES OBJECT_DEPENDS ${REPO_ROOT}/robot/robot.ino)

add_library(hexapod_sim SHARED $<TARGET_OBJECTS:robot_core>)
set_target_properties(hexapod_sim PROPERTIES PREFIX "")   # hexapod_sim.dll, not libhexapod_sim.dll

add_executable(sim_smoke tests/sim_smoke.cpp $<TARGET_OBJECTS:robot_core>)
target_include_directories(sim_smoke PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${REPO_ROOT}/shared/HexapodProtocol
                                             ${CMAKE_CURRENT_SOURCE_DIR}/shim)

if(MINGW)
  # Self-contained binaries: no libstdc++/libgcc/winpthread DLLs needed next to them.
  foreach(t hexapod_sim sim_smoke)
    target_link_options(${t} PRIVATE -static -static-libgcc -static-libstdc++)
  endforeach()
endif()
