cmake_minimum_required(VERSION 3.10)
project(context_switcher
        VERSION 0.0.1
        DESCRIPTION "allows to execute functions and lambdas on a new stack and switch between them"
        LANGUAGES CXX ASM)

set(CMAKE_CXX_STANDARD 11)

# Platform Support - Edit this when porting the context switch facility.
# Settings:
# CS_USE_BOOST              = ON/OFF        Use boost's fcontext as the assembly implementation for the context switch.
# CS_USE_FAST               = ON/OFF        Use custom implementation optimized for fast creation/return context switch.
# CMAKE_SYSTEM_PROCESSOR    = String        Target processor
# CMAKE_SYSTEM_NAME         = String        Target
#
# Typically cross compiling in cmake will set CMAKE_SYSTEM_PROCESSOR and CMAKE_SYSTEM_NAME.
# The library uses these two to select the correct assembly file for performing the context switch.
# We currently only include minimal system support in our config file. The fastest way to port the
# library is to see if one of the boost.context assembly files matches your target platform and adding
# that to tho selection script.
#
# By default we use CS_USE_FAST if available and fall back to CS_USE_BOOST if needed.
# When sanitizers are turned on (or other instrumentation) we recommend to use CS_USE_BOOST
# as its calling convention causes no problems with function entry/exit instrumentation.

message("-- Configure Context Switcher: ${CMAKE_SYSTEM_PROCESSOR} running ${CMAKE_SYSTEM_NAME}")
include(asm/cscontext/SelectAssemblyFiles.cmake)
include(asm/fcontext/SelectAssemblyFiles.cmake)

if (CS_CSCONTEXT_FOUND AND NOT THREAD_SANITIZER AND NOT CS_FORCE_FALLBACK)
    MESSAGE("-- Using cscontext implementation")
    SET(CS_CONTEXT_SWITCH_ASSEMBLY ${CS_CSCONTEXT_ASSEMBLY})
    SET(CS_USE_CSCONTEXT TRUE)
elseif (CS_FCONTEXT_FOUND)
    if (THREAD_SANITIZER)
        MESSAGE("-- Falling back to fcontext implementation (thread sanitizer active)")
    else ()
        MESSAGE("-- Falling back to fcontext implementation")
    endif ()
    SET(CS_CONTEXT_SWITCH_ASSEMBLY ${CS_FCONTEXT_ASSEMBLY})
    SET(CS_USE_CSCONTEXT FALSE)
else ()
    MESSAGE(FATAL_ERROR "Platform (${CMAKE_SYSTEM_PROCESSOR} on ${CMAKE_SYSTEM_NAME}) not supported! Please see Readme for instructions to port.")
endif ()
message("-- Configure Context Switcher: Configuration Done")

add_library(context_switcher STATIC
        ${CS_CONTEXT_SWITCH_ASSEMBLY}
        include/context_switcher/context_switcher.h src/context_switcher.cpp
        include/context_switcher/cscontext.h
        include/context_switcher/fcontext.h
        include/context_switcher/continuation.h
        include/context_switcher/context.h)

if (CS_USE_CSCONTEXT)
    target_compile_definitions(context_switcher PUBLIC CS_USE_CSCONTEXT)
else ()
    target_compile_definitions(context_switcher PUBLIC CS_USE_FCONTEXT)
endif ()

# Add everything in `./include` to be in the include path of this project
target_include_directories(context_switcher
        PUBLIC
        $<INSTALL_INTERFACE:include>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src # TODO: Set this up when we require private headers
        )

# Rules for installing the library on a system
# ...binaries
INSTALL(TARGETS context_switcher
        EXPORT context_switcher-targets
        LIBRARY DESTINATION lib/context_switcher
        ARCHIVE DESTINATION lib/context_switcher
        )
# ...all headers in `include`
INSTALL(
        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/context_switcher
        DESTINATION include
        FILES_MATCHING PATTERN "*.h*"
)
# ...allow our project to be a cmake dependency
install(
        EXPORT context_switcher-targets
        FILE context_switcherTargets.cmake
        NAMESPACE context_switcher::
        DESTINATION lib/context_switcher
)
INSTALl(
        FILES context_switcher-config.cmake
        DESTINATION lib/context_switcher
)

