﻿set(LIB_NAME Core)

file(
    GLOB_RECURSE LIB_SRC 
    LIST_DIRECTORIES false
    CONFIGURE_DEPENDS
    "${CMAKE_CURRENT_SOURCE_DIR}/*.c*"
    "${CMAKE_CURRENT_SOURCE_DIR}/*.h*"
    "${CMAKE_CURRENT_SOURCE_DIR}/*.inl"
)

list(FILTER LIB_SRC EXCLUDE REGEX Platform.h.in)
list(FILTER LIB_SRC EXCLUDE REGEX "${CMAKE_CURRENT_SOURCE_DIR}/Backend/*.*")

if(WIN32)
    foreach(SRC IN ITEMS ${LIB_SRC})
        get_filename_component(SRC_PATH "${SRC}" PATH)
        file(RELATIVE_PATH SRC_PATH_REL "${CMAKE_CURRENT_SOURCE_DIR}" "${SRC_PATH}")
        string(REPLACE "/" "\\" GROUP_PATH "${SRC_PATH_REL}")
        source_group("${GROUP_PATH}" FILES "${SRC}")
    endforeach()
endif()

#add Platform.h
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Platform.h.in" "${CMAKE_CURRENT_BINARY_DIR}/Platform.h")

set(PLATFORM_FILE "${CMAKE_CURRENT_BINARY_DIR}/Platform.h")

if("${PERIDYNO_GPU_BACKEND}" STREQUAL "CUDA")
    file(GLOB_RECURSE GPU_SRC 
        LIST_DIRECTORIES false
        CONFIGURE_DEPENDS
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/*.h*"
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/*.c*"
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/*.inl")

    if(WIN32)
        foreach(SRC IN ITEMS ${GPU_SRC})
            get_filename_component(SRC_PATH "${SRC}" PATH)
            file(RELATIVE_PATH SRC_PATH_REL "${CMAKE_CURRENT_SOURCE_DIR}/Backend" "${SRC_PATH}")
            string(REPLACE "/" "\\" GROUP_PATH "${SRC_PATH_REL}")
            source_group("${GROUP_PATH}" FILES "${SRC}")
        endforeach()
    endif()

    add_library(${LIB_NAME} STATIC ${LIB_SRC} ${GPU_SRC}) 
elseif("${PERIDYNO_GPU_BACKEND}" STREQUAL "Vulkan")
    file(GLOB_RECURSE GPU_SRC 
        LIST_DIRECTORIES false
        CONFIGURE_DEPENDS
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Vulkan/*.h*"
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Vulkan/*.c*"
        "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Vulkan/*.inl")

    if(WIN32)
        foreach(SRC IN ITEMS ${GPU_SRC})
            get_filename_component(SRC_PATH "${SRC}" PATH)
            file(RELATIVE_PATH SRC_PATH_REL "${CMAKE_CURRENT_SOURCE_DIR}/Backend" "${SRC_PATH}")
            string(REPLACE "/" "\\" GROUP_PATH "${SRC_PATH_REL}")
            source_group("${GROUP_PATH}" FILES "${SRC}")
        endforeach()
    endif()

    add_library(${LIB_NAME} SHARED ${LIB_SRC} ${GPU_SRC}) 
else()
    if(WIN32)
        foreach(SRC IN ITEMS ${GPU_SRC})
            get_filename_component(SRC_PATH "${SRC}" PATH)
            file(RELATIVE_PATH SRC_PATH_REL "${CMAKE_CURRENT_SOURCE_DIR}/Backend" "${SRC_PATH}")
            string(REPLACE "/" "\\" GROUP_PATH "${SRC_PATH_REL}")
            source_group("${GROUP_PATH}" FILES "${SRC}")
        endforeach()
    endif()
    
    add_library(${LIB_NAME} STATIC ${LIB_SRC} ${GPU_SRC}) 
endif()

add_compile_definitions(GLM_ENABLE_EXPERIMENTAL)
add_compile_definitions(_ENABLE_EXTENDED_ALIGNED_STORAGE)

if(WIN32)
    set_target_properties(${LIB_NAME} PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
elseif(UNIX)
    if (CMAKE_BUILD_TYPE MATCHES Debug)
        set_target_properties(${LIB_NAME} PROPERTIES
            RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/Debug")
    else()
        set_target_properties(${LIB_NAME} PROPERTIES
            RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/Release")
    endif()
endif()

if(WIN32)
    target_compile_options(${LIB_NAME} PRIVATE -Xcompiler "/wd 4819") 
endif()

file(RELATIVE_PATH PROJECT_PATH_REL "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
set_target_properties(${LIB_NAME} PROPERTIES FOLDER "Engine")
set_target_properties(${LIB_NAME} PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
set_target_properties(${LIB_NAME} PROPERTIES CUDA_ARCHITECTURES "${CUDA_ARCH_FLAGS}")
set_target_properties(${LIB_NAME} PROPERTIES
    OUTPUT_NAME "dyno${LIB_NAME}-${PERIDYNO_LIBRARY_VERSION}")

if("${PERIDYNO_GPU_BACKEND}" STREQUAL "CUDA")
    #To resolve the error: Target "..." INTERFACE_INCLUDE_DIRECTORIES property contains path: "..." which is prefixed in the build directory.
    #    target_include_directories(${LIB_NAME} PUBLIC ${PERIDYNO_INCLUDE_PATH}) # for generated files
    target_include_directories(${LIB_NAME} PUBLIC 
        $<BUILD_INTERFACE:${PERIDYNO_ROOT}/src/Core>
        $<BUILD_INTERFACE:${PERIDYNO_ROOT}/src/Core/Backend/Cuda>
        $<BUILD_INTERFACE:${PERIDYNO_ROOT}/external>
        $<BUILD_INTERFACE:${PERIDYNO_ROOT}/external/eigen>
        $<BUILD_INTERFACE:${PERIDYNO_ROOT}/external/glm-0.9.9.7>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
        $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}>
        $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}/${LIB_NAME}>
        $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}/${LIB_NAME}/Backend/Cuda>
        $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}/external/glm-0.9.9.7>)

	#To disable the warning "calling a constexpr __host__ function("***") from a __host__ __device__ function("***") is not allowed."
	target_compile_options(${LIB_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>)
    target_compile_options(${LIB_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-lineinfo>)

	install(TARGETS ${LIB_NAME}
	    EXPORT ${LIB_NAME}Targets
	    RUNTIME  DESTINATION  ${PERIDYNO_RUNTIME_INSTALL_DIR}
	    LIBRARY  DESTINATION  ${PERIDYNO_LIBRARY_INSTALL_DIR}
	    ARCHIVE  DESTINATION  ${PERIDYNO_ARCHIVE_INSTALL_DIR}
	    )

	install(EXPORT ${LIB_NAME}Targets DESTINATION ${PERIDYNO_CMAKE_CONFIG_INSTALL_DIR}
	    FILE ${LIB_NAME}Targets.cmake)

	get_property(LOCAL_CMAKES_NAMES GLOBAL PROPERTY "GLOBAL_CMAKES_NAMES")
	list(APPEND LOCAL_CMAKES_NAMES "${LIB_NAME}Targets.cmake")    
	set_property(GLOBAL PROPERTY GLOBAL_CMAKES_NAMES ${LOCAL_CMAKES_NAMES})

	file(GLOB CORE_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.inl")
	install(FILES ${CORE_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core)

	file(GLOB CORE_ALGORITHM_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Algorithm/*.h")
	install(FILES ${CORE_ALGORITHM_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Algorithm)

	file(GLOB CORE_VECTOR_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Vector/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Vector/*.inl")
	install(FILES ${CORE_VECTOR_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Vector)

	file(GLOB CORE_MATRIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Matrix/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Matrix/*.inl")
	install(FILES ${CORE_MATRIX_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Matrix)

    file(GLOB CORE_MATRIXEXT_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/MatrixExt/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/MatrixExt/*.inl")
	install(FILES ${CORE_MATRIXEXT_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/MatrixExt)

    file(GLOB CORE_SMEM_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/SMEM/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/SMEM/*.inl")
	install(FILES ${CORE_SMEM_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/SMEM)

	file(GLOB CORE_RIGID_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Rigid/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Rigid/*.inl")
	install(FILES ${CORE_RIGID_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Rigid)

	file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Array/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Array/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Array)

    file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/CCD/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/CCD/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/CCD)

    file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Primitive/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Primitive/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Primitive)

    file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Math/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Math/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Math)

	file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/STL/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/STL/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/STL)

    file(GLOB BACKEND_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/*.*")
	install(FILES ${BACKEND_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Backend/Cuda)

    file(GLOB BACKEND_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/Algorithm/*.*")
	install(FILES ${BACKEND_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Backend/Cuda/Algorithm)

    file(GLOB BACKEND_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/Array/*.*")
	install(FILES ${BACKEND_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Backend/Cuda/Array)

    file(GLOB BACKEND_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Backend/Cuda/SparseMatrix/*.*")
	install(FILES ${BACKEND_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Backend/Cuda/SparseMatrix)

	install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Platform.h"  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/)

	install(DIRECTORY "${CMAKE_SOURCE_DIR}/external/glm-0.9.9.7/" DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/external/glm-0.9.9.7/)

elseif("${PERIDYNO_GPU_BACKEND}" STREQUAL "Vulkan")
	target_include_directories(${LIB_NAME} PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/Core>
	$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/Core/Backend/Vulkan>)

	include_directories(${CMAKE_SOURCE_DIR}/external/glslang/glslang/Include)

	if(WIN32)
    	    target_link_libraries(${LIB_NAME} ${Vulkan_LIBRARY} ${WINLIBS} glslang)
	else(UNIX)
	    target_link_libraries(${LIB_NAME} ${Vulkan_LIBRARY} ${XCB_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} glslang)
	endif()


    	install(TARGETS ${LIB_NAME}
	    EXPORT ${LIB_NAME}Targets
	    RUNTIME  DESTINATION  ${PERIDYNO_RUNTIME_INSTALL_DIR}
	    LIBRARY  DESTINATION  ${PERIDYNO_LIBRARY_INSTALL_DIR}
	    ARCHIVE  DESTINATION  ${PERIDYNO_ARCHIVE_INSTALL_DIR}
	    )

	install(EXPORT ${LIB_NAME}Targets DESTINATION ${PERIDYNO_CMAKE_CONFIG_INSTALL_DIR}
	    FILE ${LIB_NAME}Targets.cmake)

	get_property(LOCAL_CMAKES_NAMES GLOBAL PROPERTY "GLOBAL_CMAKES_NAMES")
	list(APPEND LOCAL_CMAKES_NAMES "${LIB_NAME}Targets.cmake")    
	set_property(GLOBAL PROPERTY GLOBAL_CMAKES_NAMES ${LOCAL_CMAKES_NAMES})

	file(GLOB CORE_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.inl")
	install(FILES ${CORE_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core)
else()
    target_include_directories(${LIB_NAME} PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/Core>
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/external>
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/external/eigen>
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/external/glm-0.9.9.7>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
    $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}>
    $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}/${LIB_NAME}>
    $<INSTALL_INTERFACE:${PERIDYNO_INC_INSTALL_DIR}/external/glm-0.9.9.7>)

	install(TARGETS ${LIB_NAME}
	    EXPORT ${LIB_NAME}Targets
	    RUNTIME  DESTINATION  ${PERIDYNO_RUNTIME_INSTALL_DIR}
	    LIBRARY  DESTINATION  ${PERIDYNO_LIBRARY_INSTALL_DIR}
	    ARCHIVE  DESTINATION  ${PERIDYNO_ARCHIVE_INSTALL_DIR}
	    )

	install(EXPORT ${LIB_NAME}Targets DESTINATION ${PERIDYNO_CMAKE_CONFIG_INSTALL_DIR}
	    FILE ${LIB_NAME}Targets.cmake)

	get_property(LOCAL_CMAKES_NAMES GLOBAL PROPERTY "GLOBAL_CMAKES_NAMES")
	list(APPEND LOCAL_CMAKES_NAMES "${LIB_NAME}Targets.cmake")    
	set_property(GLOBAL PROPERTY GLOBAL_CMAKES_NAMES ${LOCAL_CMAKES_NAMES})

	file(GLOB CORE_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.inl")
	install(FILES ${CORE_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core)

	file(GLOB CORE_ALGORITHM_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Algorithm/*.h")
	install(FILES ${CORE_ALGORITHM_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Algorithm)

	file(GLOB CORE_VECTOR_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Vector/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Vector/*.inl")
	install(FILES ${CORE_VECTOR_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Vector)

	file(GLOB CORE_MATRIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Matrix/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Matrix/*.inl")
	install(FILES ${CORE_MATRIX_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Matrix)
    
    file(GLOB CORE_MATRIXEXT_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/MatrixExt/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/MatrixExt/*.inl")
	install(FILES ${CORE_MATRIXEXT_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/MatrixExt)

    file(GLOB CORE_SMEM_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/SMEM/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/SMEM/*.inl")
	install(FILES ${CORE_SMEM_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/SMEM)

	file(GLOB CORE_RIGID_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Rigid/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Rigid/*.inl")
	install(FILES ${CORE_RIGID_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Rigid)

	file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Array/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/Array/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/Array)

	file(GLOB CORE_ARRAY_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/STL/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/STL/*.inl")
	install(FILES ${CORE_ARRAY_HEADER}  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/STL)

	install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Platform.h"  DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/Core/)

	install(DIRECTORY "${CMAKE_SOURCE_DIR}/external/glm-0.9.9.7/" DESTINATION ${PERIDYNO_INC_INSTALL_DIR}/external/glm-0.9.9.7/)

endif()
