cmake_minimum_required(VERSION 3.20)
project(octavian_harmonics_native LANGUAGES CXX)
# Use upstream headers only; do not build or replace the ASSET pip wheel.
set(ASSET_SOURCE_DIR "$ENV{ASSET_SOURCE_DIR}" CACHE PATH "ASSET v0.5.1 source with initialized submodules")
if(NOT EXISTS "${ASSET_SOURCE_DIR}/src/VectorFunctions/VectorFunction.h")
  message(FATAL_ERROR "Set ASSET_SOURCE_DIR to upstream ASSET v0.5.1 with initialized submodules")
endif()
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  message(FATAL_ERROR "ASSET 0.5.1 pip wheels use Clang; use a matching Clang toolchain")
endif()
find_package(Git REQUIRED)
execute_process(COMMAND "${GIT_EXECUTABLE}" -C "${ASSET_SOURCE_DIR}" rev-parse HEAD OUTPUT_VARIABLE ASSET_REVISION OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
if(NOT ASSET_REVISION STREQUAL "6cb73ac174b140ecc6ac1b9563012424f2f0a748")
  message(FATAL_ERROR "Use the upstream ASSET v0.5.1 commit 6cb73ac174b140ecc6ac1b9563012424f2f0a748")
endif()
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|amd64)$")
  message(FATAL_ERROR "The native backend currently targets the ASSET x86-64 AVX2 pip wheel")
endif()
execute_process(COMMAND "${GIT_EXECUTABLE}" -C "${ASSET_SOURCE_DIR}" submodule status dep/eigen dep/pybind11 dep/fmt OUTPUT_VARIABLE ASSET_SUBMODULES COMMAND_ERROR_IS_FATAL ANY)
if(ASSET_SUBMODULES MATCHES "(^|\n)[+U-]")
  message(FATAL_ERROR "Initialize the pinned ASSET submodules: git submodule update --init dep/eigen dep/pybind11 dep/fmt")
endif()
set(CMAKE_CXX_STANDARD 17)
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
set(PYBIND11_FINDPYTHON ON)
add_subdirectory("${ASSET_SOURCE_DIR}/dep/pybind11" "${CMAKE_BINARY_DIR}/pybind11")
pybind11_add_module(octavian_harmonics_native NO_EXTRAS harmonics.cpp "${ASSET_SOURCE_DIR}/src/Utils/MemoryManagement.cpp")
target_include_directories(octavian_harmonics_native PRIVATE "${ASSET_SOURCE_DIR}/src" "${ASSET_SOURCE_DIR}/dep/eigen" "${ASSET_SOURCE_DIR}/dep/fmt/include")
foreach(directory VectorFunctions Solvers TypeDefs Utils OptimalControl Integrators)
  target_include_directories(octavian_harmonics_native PRIVATE "${ASSET_SOURCE_DIR}/src/${directory}")
endforeach()
target_compile_definitions(octavian_harmonics_native PRIVATE EIGEN_INITIALIZE_MATRICES_BY_ZERO EIGEN_DONT_PARALLELIZE ASSET_MEMORYMAN ASSET_DEFAULT_ARENA_SIZE=256 FMT_HEADER_ONLY)
if(WIN32)
  target_compile_options(octavian_harmonics_native PRIVATE /arch:AVX2)
  target_compile_definitions(octavian_harmonics_native PRIVATE _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
else()
  target_compile_options(octavian_harmonics_native PRIVATE -mavx2 -mfma)
endif()
install(TARGETS octavian_harmonics_native LIBRARY DESTINATION . RUNTIME DESTINATION .)

# Preserve notices for the upstream code compiled into this extension.
install(FILES "${ASSET_SOURCE_DIR}/LICENSE.txt" DESTINATION octavian_harmonics_native_licenses RENAME ASSET.txt)
install(FILES "${ASSET_SOURCE_DIR}/dep/eigen/COPYING.MPL2" DESTINATION octavian_harmonics_native_licenses RENAME Eigen-MPL2.txt)
install(FILES "${ASSET_SOURCE_DIR}/dep/eigen/COPYING.BSD" DESTINATION octavian_harmonics_native_licenses RENAME Eigen-BSD.txt)
install(FILES "${ASSET_SOURCE_DIR}/dep/pybind11/LICENSE" DESTINATION octavian_harmonics_native_licenses RENAME pybind11.txt)
install(FILES "${ASSET_SOURCE_DIR}/dep/fmt/LICENSE.rst" DESTINATION octavian_harmonics_native_licenses RENAME fmt.txt)
