# This file is part of the mlhp project. License: See LICENSE
#
# Example of building a C++ extension module against a pip installed mlhp, which doubles as
# the test that a wheel is a complete dependency: headers, exported symbols, a pybind11
# type registry shared with mlhp's own module, and one shared OpenMP runtime.
#
# Shipped inside the wheel as well, so users obtain these files against their own
# installation with mlhp.example( "cpp_extension", path="<directory>" ). See the docstring
# of extension_test.py for what the example does.
#
# Configure aborts with the pybind11 version to install if it does not match mlhp's.
#
#   pip install mlhp pybind11
#   cmake -S <this directory> -B <builddir>
#   cmake --build <builddir> --config Release
#   ctest --test-dir <builddir> -C Release --output-on-failure

# 3.19 for COMMAND_ERROR_IS_FATAL and Development.Module below
cmake_minimum_required( VERSION 3.19 )

project( mlhp_extension LANGUAGES CXX )

# Both components: pybind11 finds Python again below and a cached interpreter-only result
# leaves python_add_library undefined.
find_package( Python COMPONENTS Interpreter Development.Module REQUIRED )

# Without this pybind11 uses its classic finder, which picks whichever interpreter comes
# first on PATH rather than the one given in Python_EXECUTABLE. Building against a different
# python than mlhp was built for fails only later, when both modules are imported together.
if( NOT DEFINED PYBIND11_FINDPYTHON )
    set( PYBIND11_FINDPYTHON NEW )
endif( )

# Both ship their cmake package inside the python distribution
foreach( package mlhp pybind11 )
    if( NOT DEFINED ${package}_DIR )
        execute_process( COMMAND ${Python_EXECUTABLE} -c
                         "import ${package}; print(${package}.get_cmake_dir())"
                         OUTPUT_VARIABLE ${package}_DIR
                         OUTPUT_STRIP_TRAILING_WHITESPACE
                         COMMAND_ERROR_IS_FATAL ANY )
    endif( )
endforeach( )

find_package( mlhp CONFIG REQUIRED )
find_package( pybind11 CONFIG REQUIRED )

# Stricter than the internals version that governs compatibility, so that a bumped submodule
# is noticed here rather than in a downstream project.
if( mlhp_PYBIND11_VERSION AND NOT pybind11_VERSION VERSION_EQUAL mlhp_PYBIND11_VERSION )
    message( FATAL_ERROR "Found pybind11 ${pybind11_VERSION}, but this mlhp was built "
                         "against ${mlhp_PYBIND11_VERSION}. Install the matching one with "
                         "\"pip install pybind11==${mlhp_PYBIND11_VERSION}\"." )
endif( )

pybind11_add_module( mlhp_extension extension.cpp )

target_link_libraries( mlhp_extension PRIVATE mlhp::core )

# A test so the per-config module subdirectory does not have to be spelled out
enable_testing( )

add_test( NAME extension COMMAND ${Python_EXECUTABLE} -X faulthandler
          ${CMAKE_CURRENT_SOURCE_DIR}/extension_test.py $<TARGET_FILE_DIR:mlhp_extension> )
