
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/flexiblas_api.h.in ${CMAKE_BINARY_DIR}/include/flexiblas_api.h)


ADD_SUBDIRECTORY(fallback_blas)

IF(LAPACK)
ADD_SUBDIRECTORY(fallback_lapack)
ENDIF()

SET (COMMON_SRC
	mgmt/hooks.c
	mgmt.c
    paths.c
    hooks.c
    utils.c
    sh_utils.c
	flexiblas_printf.c
    common.c
)

SET ( SRC
	flexiblas.c
	flexiblas_api.c
	loader.c
	hook_loader.c
	xerbla.c
	lsame.c
	set_num_threads.c
	wrap_cblas.c
    cabs.c
    ${COMMON_SRC}
)

SET (FLEXIBLAS_MGMT_SRC
    ${COMMON_SRC}
)

SET (FLEXIBLAS_API_SRC
	flexiblas_api_standalone.c
)

IF ( FLEXIBLAS_ABI_INTEL)
	SET (SRC ${SRC} wrapper_blas_intel.c)
ELSE ()
	SET (SRC ${SRC} wrapper_blas_gnu.c)
ENDIF()


SET ( CBLAS_SRC
	# Globlas
	cblas_interface/cblas_globals.c
	cblas_interface/cblas_xerbla.c
	# Double
	cblas_interface/cblas_dasum.c
	cblas_interface/cblas_daxpy.c
	cblas_interface/cblas_dcopy.c
	cblas_interface/cblas_ddot.c
	cblas_interface/cblas_dgbmv.c
	cblas_interface/cblas_dgemm.c
	cblas_interface/cblas_dgemv.c
	cblas_interface/cblas_dger.c
	cblas_interface/cblas_dnrm2.c
	cblas_interface/cblas_drot.c
	cblas_interface/cblas_drotg.c
	cblas_interface/cblas_drotm.c
	cblas_interface/cblas_drotmg.c
	cblas_interface/cblas_dsbmv.c
	cblas_interface/cblas_dscal.c
	cblas_interface/cblas_dsdot.c
	cblas_interface/cblas_dspmv.c
	cblas_interface/cblas_dspr.c
	cblas_interface/cblas_dspr2.c
	cblas_interface/cblas_dswap.c
	cblas_interface/cblas_dsymm.c
	cblas_interface/cblas_dsymv.c
	cblas_interface/cblas_dsyr.c
	cblas_interface/cblas_dsyr2.c
	cblas_interface/cblas_dsyr2k.c
	cblas_interface/cblas_dsyrk.c
	cblas_interface/cblas_dtbmv.c
	cblas_interface/cblas_dtbsv.c
	cblas_interface/cblas_dtpmv.c
	cblas_interface/cblas_dtpsv.c
	cblas_interface/cblas_dtrmm.c
	cblas_interface/cblas_dtrmv.c
	cblas_interface/cblas_dtrsm.c
	cblas_interface/cblas_dtrsv.c
	cblas_interface/cblas_dzasum.c
	cblas_interface/cblas_dznrm2.c
	cblas_interface/cblas_idamax.c
	# Single
	cblas_interface/cblas_sasum.c
	cblas_interface/cblas_saxpy.c
	cblas_interface/cblas_scasum.c
	cblas_interface/cblas_scnrm2.c
	cblas_interface/cblas_scopy.c
	cblas_interface/cblas_sdot.c
	cblas_interface/cblas_sdsdot.c
	cblas_interface/cblas_sgbmv.c
	cblas_interface/cblas_sgemm.c
	cblas_interface/cblas_sgemv.c
	cblas_interface/cblas_sger.c
	cblas_interface/cblas_snrm2.c
	cblas_interface/cblas_srot.c
	cblas_interface/cblas_srotg.c
	cblas_interface/cblas_srotm.c
	cblas_interface/cblas_srotmg.c
	cblas_interface/cblas_ssbmv.c
	cblas_interface/cblas_sscal.c
	cblas_interface/cblas_sspmv.c
	cblas_interface/cblas_sspr2.c
	cblas_interface/cblas_sspr.c
	cblas_interface/cblas_sswap.c
	cblas_interface/cblas_ssymm.c
	cblas_interface/cblas_ssymv.c
	cblas_interface/cblas_ssyr2.c
	cblas_interface/cblas_ssyr2k.c
	cblas_interface/cblas_ssyr.c
	cblas_interface/cblas_ssyrk.c
	cblas_interface/cblas_stbmv.c
	cblas_interface/cblas_stbsv.c
	cblas_interface/cblas_stpmv.c
	cblas_interface/cblas_stpsv.c
	cblas_interface/cblas_strmm.c
	cblas_interface/cblas_strmv.c
	cblas_interface/cblas_strsm.c
	cblas_interface/cblas_strsv.c
	cblas_interface/cblas_isamax.c
	# Complex Single
	cblas_interface/cblas_caxpy.c
	cblas_interface/cblas_ccopy.c
	cblas_interface/cblas_cdotc_sub.c
	cblas_interface/cblas_cdotu_sub.c
	cblas_interface/cblas_cgbmv.c
	cblas_interface/cblas_cgemm.c
	cblas_interface/cblas_cgemv.c
	cblas_interface/cblas_cgerc.c
	cblas_interface/cblas_cgeru.c
	cblas_interface/cblas_chbmv.c
	cblas_interface/cblas_chemm.c
	cblas_interface/cblas_chemv.c
	cblas_interface/cblas_cher2.c
	cblas_interface/cblas_cher2k.c
	cblas_interface/cblas_cher.c
	cblas_interface/cblas_cherk.c
	cblas_interface/cblas_chpmv.c
	cblas_interface/cblas_chpr2.c
	cblas_interface/cblas_chpr.c
	cblas_interface/cblas_crotg.c
	cblas_interface/cblas_csrot.c
	cblas_interface/cblas_cscal.c
	cblas_interface/cblas_csscal.c
	cblas_interface/cblas_cswap.c
	cblas_interface/cblas_csymm.c
	cblas_interface/cblas_csyr2k.c
	cblas_interface/cblas_csyrk.c
	cblas_interface/cblas_ctbmv.c
	cblas_interface/cblas_ctbsv.c
	cblas_interface/cblas_ctpmv.c
	cblas_interface/cblas_ctpsv.c
	cblas_interface/cblas_ctrmm.c
	cblas_interface/cblas_ctrmv.c
	cblas_interface/cblas_ctrsm.c
	cblas_interface/cblas_ctrsv.c
	cblas_interface/cblas_icamax.c
	# Complex Double
	cblas_interface/cblas_zaxpy.c
	cblas_interface/cblas_zcopy.c
	cblas_interface/cblas_zdotc_sub.c
	cblas_interface/cblas_zdotu_sub.c
	cblas_interface/cblas_zgbmv.c
	cblas_interface/cblas_zgemm.c
	cblas_interface/cblas_zgemv.c
	cblas_interface/cblas_zgerc.c
	cblas_interface/cblas_zgeru.c
	cblas_interface/cblas_zhbmv.c
	cblas_interface/cblas_zhemm.c
	cblas_interface/cblas_zhemv.c
	cblas_interface/cblas_zher2.c
	cblas_interface/cblas_zher2k.c
	cblas_interface/cblas_zher.c
	cblas_interface/cblas_zherk.c
	cblas_interface/cblas_zhpmv.c
	cblas_interface/cblas_zhpr2.c
	cblas_interface/cblas_zhpr.c
    cblas_interface/cblas_zrotg.c
    cblas_interface/cblas_zdrot.c
	cblas_interface/cblas_zscal.c
	cblas_interface/cblas_zdscal.c
	cblas_interface/cblas_zswap.c
	cblas_interface/cblas_zsymm.c
    cblas_interface/cblas_zsyr2k.c
	cblas_interface/cblas_zsyrk.c
	cblas_interface/cblas_ztbmv.c
	cblas_interface/cblas_ztbsv.c
	cblas_interface/cblas_ztpmv.c
	cblas_interface/cblas_ztpsv.c
	cblas_interface/cblas_ztrmm.c
	cblas_interface/cblas_ztrmv.c
	cblas_interface/cblas_ztrsm.c
	cblas_interface/cblas_ztrsv.c
	cblas_interface/cblas_izamax.c
    cblas_interface/cblas_daxpby.c
    cblas_interface/cblas_saxpby.c
    cblas_interface/cblas_caxpby.c
    cblas_interface/cblas_zaxpby.c
    cblas_interface/cblas_simatcopy.c
    cblas_interface/cblas_dimatcopy.c
    cblas_interface/cblas_cimatcopy.c
    cblas_interface/cblas_zimatcopy.c
    cblas_interface/cblas_somatcopy.c
    cblas_interface/cblas_domatcopy.c
    cblas_interface/cblas_comatcopy.c
    cblas_interface/cblas_zomatcopy.c
    cblas_interface/cblas_dgeadd.c
    cblas_interface/cblas_cgeadd.c
    cblas_interface/cblas_zgeadd.c
    cblas_interface/cblas_sgeadd.c


    )
IF (CBLAS STREQUAL ON)
	SET (SRC ${SRC} ${CBLAS_SRC})
ENDIF()

#
# LAPACK
#
IF ( LAPACK )
	# 3.7.1 and 3.7.0 share the same api/abi
	IF(LAPACK_API_VERSION STREQUAL "3.11.0")
		SET(_LAPACK_FILE_SUFFIX 3_11_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.11.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_11_0-wodprc) #
    ELSEIF(LAPACK_API_VERSION STREQUAL "3.10.1")
		SET(_LAPACK_FILE_SUFFIX 3_10_1)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.10.1-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_10_1-wodprc) #
    ELSEIF(LAPACK_API_VERSION STREQUAL "3.10.0")
		SET(_LAPACK_FILE_SUFFIX 3_10_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.10.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_10_0-wodprc) #
    ELSEIF(LAPACK_API_VERSION STREQUAL "3.9.1")
		SET(_LAPACK_FILE_SUFFIX 3_9_1)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.9.1-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_9_1-wodprc) #
    ELSEIF(LAPACK_API_VERSION STREQUAL "3.9.0")
		SET(_LAPACK_FILE_SUFFIX 3_9_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.9.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_9_0-wodprc) #
    ELSEIF(LAPACK_API_VERSION STREQUAL "3.8.0")
		SET(_LAPACK_FILE_SUFFIX 3_8_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.8.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_8_0-wodprc) #
	ELSEIF(LAPACK_API_VERSION STREQUAL "3.7.1")
		SET(_LAPACK_FILE_SUFFIX 3_7_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.7.1-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_7_0-wodprc) #
	ELSEIF(LAPACK_API_VERSION STREQUAL "3.7.0")
		SET(_LAPACK_FILE_SUFFIX 3_7_0)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.7.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_7_0-wodprc) #
	ELSEIF(LAPACK_API_VERSION STREQUAL "3.6.1")
		SET(_LAPACK_FILE_SUFFIX 3_6_1)
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.6.1-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_6_1-wodprc) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.6.0")
		SET(_LAPACK_FILE_SUFFIX 3_6_0) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.6.0-wodprc")
		SET(_LAPACK_FILE_SUFFIX 3_6_0-wodprc) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.5.0")
		SET(_LAPACK_FILE_SUFFIX 3_5_0) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.4.2")
		SET(_LAPACK_FILE_SUFFIX 3_4_2) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.4.1")
		SET(_LAPACK_FILE_SUFFIX 3_4_1) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.4.0")
		SET(_LAPACK_FILE_SUFFIX 3_4_0) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.3.1")
		SET(_LAPACK_FILE_SUFFIX 3_3_1) #
	ELSEIF (LAPACK_API_VERSION STREQUAL "3.3.0")
		SET(_LAPACK_FILE_SUFFIX 3_3_0) #
	ENDIF()
	INCLUDE(lapack_interface/lapack_${_LAPACK_FILE_SUFFIX}.cmake)

	SET (SRC ${SRC} ${LAPACK_SRC} lapack_interface/ilaver.c
		lapack_interface/load_lapack_${_LAPACK_FILE_SUFFIX}.c
        lapack_interface/load_lapack_${_LAPACK_FILE_SUFFIX}_fallback.c
	)

	FILE(COPY lapack_interface/lapack_${_LAPACK_FILE_SUFFIX}.h DESTINATION ${PROJECT_BINARY_DIR}/include/)
	FILE(RENAME  ${PROJECT_BINARY_DIR}/include/lapack_${_LAPACK_FILE_SUFFIX}.h ${PROJECT_BINARY_DIR}/include/lapack.h)
	FILE(COPY lapack_interface/flexiblas_real_lapack_${_LAPACK_FILE_SUFFIX}.h DESTINATION ${PROJECT_BINARY_DIR}/include/)
	FILE(RENAME  ${PROJECT_BINARY_DIR}/include/flexiblas_real_lapack_${_LAPACK_FILE_SUFFIX}.h ${PROJECT_BINARY_DIR}/include/flexiblas_real_lapack.h)

ENDIF()

FIND_PACKAGE(OpenMP)

INCLUDE_DIRECTORIES(${INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(flexiblas SHARED ${SRC}) #  $<TARGET_OBJECTS:cscutils_src>)
add_executable(flexiblas-tool flexiblas_tool.c tool/hookhandling.c tool/blashandling.c ${COMMON_SRC} ) # $<TARGET_OBJECTS:cscutils_src>)

IF (LINK_OPENMP)
    TARGET_LINK_LIBRARIES(flexiblas ${LIBS} cscutils OpenMP::OpenMP_C)
    TARGET_LINK_LIBRARIES(flexiblas-tool PRIVATE flexiblas_mgmt ${LIBS} cscutils OpenMP::OpenMP_C)
ELSE()
    TARGET_LINK_LIBRARIES(flexiblas ${LIBS} cscutils) # OpenMP::OpenMP_C)
    TARGET_LINK_LIBRARIES(flexiblas-tool PRIVATE flexiblas_mgmt ${LIBS} cscutils) # OpenMP::OpenMP_C)
ENDIF()


add_library(flexiblas_mgmt SHARED ${FLEXIBLAS_MGMT_SRC}) # $<TARGET_OBJECTS:cscutils_src>)
TARGET_LINK_LIBRARIES(flexiblas_mgmt ${LIBS} cscutils )

add_library(flexiblas_api SHARED ${FLEXIBLAS_API_SRC} ) # $<TARGET_OBJECTS:cscutils_src>)
TARGET_LINK_LIBRARIES(flexiblas_api ${DL_LIB} cscutils c)

set(GENERIC_LIB_VERSION "${FLEXIBLAS_VERSION_MAJOR}.${FLEXIBLAS_VERSION_MINOR}")
set(GENERIC_LIB_SOVERSION "${FLEXIBLAS_VERSION_MAJOR}")


add_executable(flexiblas-config flexiblas-config.c)

IF ( C_W_PEDANTIC )
    target_compile_options(flexiblas PRIVATE "-Wpedantic")
    target_compile_options(flexiblas-tool PRIVATE "-Wpedantic")
    target_compile_options(flexiblas_mgmt PRIVATE "-Wpedantic")
    target_compile_options(flexiblas_api PRIVATE "-Wpedantic")
    target_compile_options(flexiblas-config PRIVATE "-Wpedantic")
ENDIF()






IF ( NOT ${CMAKE_C_COMPILER_ID} MATCHES "XL")
 	SET_TARGET_PROPERTIES(flexiblas PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} LINK_FLAGS "-Bsymbolic" )
 	SET_TARGET_PROPERTIES(flexiblas_mgmt PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} LINK_FLAGS "-Bsymbolic" )
 	SET_TARGET_PROPERTIES(flexiblas_api PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} LINK_FLAGS "-Bsymbolic" )
ENDIF()



IF (FLEXIBLAS_ABI_INTEL)
	SET_TARGET_PROPERTIES(flexiblas PROPERTIES OUTPUT_NAME flexiblas_intel)
ENDIF()

IF (FLEXIBLAS_ABI_IBM)
	SET_TARGET_PROPERTIES(flexiblas PROPERTIES OUTPUT_NAME flexiblas_xl)
ENDIF()


IF(INTEGER8 STREQUAL ON)
	SET_TARGET_PROPERTIES(flexiblas      PROPERTIES OUTPUT_NAME ${flexiblasname})
	SET_TARGET_PROPERTIES(flexiblas_api  PROPERTIES OUTPUT_NAME ${flexiblasname}_api)
	SET_TARGET_PROPERTIES(flexiblas_mgmt PROPERTIES OUTPUT_NAME ${flexiblasname}_mgmt)
	SET_TARGET_PROPERTIES(flexiblas-tool PROPERTIES OUTPUT_NAME ${flexiblasname})
    SET_TARGET_PROPERTIES(flexiblas-config PROPERTIES OUTPUT_NAME ${flexiblasname}-config)

	IF (USE_INTERFACE_INTEL)
		SET_TARGET_PROPERTIES(flexiblas PROPERTIES OUTPUT_NAME ${flexiblasname}_intel)
	ENDIF()
ELSE ()
	SET_TARGET_PROPERTIES(flexiblas-tool PROPERTIES OUTPUT_NAME flexiblas)
ENDIF()


install(TARGETS flexiblas LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE  DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
install(TARGETS flexiblas_mgmt LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE  DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
install(TARGETS flexiblas_api LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ARCHIVE  DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})

install(TARGETS flexiblas-tool RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
install(TARGETS flexiblas-config RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})

INCLUDE(CheckBlasZdotcMKL)
INCLUDE(CheckFortranFunctionExists)
INCLUDE(CheckFunctionExists)

# SET(BLA_STATIC TRUE)
MACRO(BuildBackendBlas VENDOR BACKEND_CODE)
    MESSAGE(STATUS "Build additional BLAS interface: ${VENDOR}")
    MESSAGE(STATUS "-- Libs: ${${VENDOR}_LIBRARY}")
    MESSAGE(STATUS "-- Linker Flags: ${${VENDOR}_LINKER_FLAGS}")

    #
    # Configure the found backend
    #
    CheckBlasZdotcMKL("${${VENDOR}_LIBRARY}" "" ${INTEGER8})
    SET(__CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
    SET(CMAKE_REQUIRED_LIBRARIES ${${VENDOR}_LIBRARY})

    UNSET(ISFLEXIBLAS CACHE)
    UNSET(DAXPY CACHE)
    UNSET(MKL_OMATCOPY CACHE)
    UNSET(CBLAS_DAXPY CACHE)
    UNSET(_MKL_VERSION CACHE)
    Check_Function_Exists(flexiblas_exit ISFLEXIBLAS)
    Check_Fortran_Function_Exists(DAXPY  DAXPY)
    Check_Function_Exists(cblas_daxpy  CBLAS_DAXPY)
    Check_Function_Exists(MKL_Get_Version _MKL_VERSION)

    # Use the MKL Backend Code if it is MKL
    IF(_MKL_VERSION)
        SET(BACKEND_CODE backends/intel_mkl/backend.c)
    ENDIF()

    SET(CMAKE_REQUIRED_LIBRARIES ${__CMAKE_REQUIRED_LIBRARIES})

    IF(NOT DAXPY)
        MESSAGE(FATAL_ERROR "${VENDOR} library does not contain a BLAS implementation or does not link.")
    ENDIF()

    IF(ISFLEXIBLAS)
        MESSAGE(FATAL_ERROR "${VENDOR} (${${VENDOR}_LIBRARY}) contains FlexiBLAS. Disable the use with -D${VENDOR}=OFF")
    ENDIF()

    UNSET(EXTRA_FLAGS CACHE)
    string(TOLOWER ${VENDOR} ivendor)


    #
    # Create the wrapper
    #
    ADD_LIBRARY(flexiblas_${ivendor} SHARED ${BACKEND_CODE})
    IF (INTEGER8 STREQUAL ON OR BLAS_INTERFACE64)
        SET(EXTRA_FLAGS "-DBACKEND_INTEGER8")
    ELSE ()
        SET(EXTRA_FLAGS "")
    ENDIF()
    IF (ZDOTC_MKL)
        MESSAGE(STATUS "${VENDOR} uses Intel ZDOTC")
        SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DZDOTC_MKL")
    ENDIF (ZDOTC_MKL)

    IF(CBLAS_DAXPY AND CBLAS STREQUAL ON)
        MESSAGE(STATUS "Add CBLAS in dummy library")
        SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DCBLAS_INTERFACE")
    ENDIF()

	SET_TARGET_PROPERTIES(flexiblas_${ivendor} PROPERTIES COMPILE_FLAGS "${EXTRA_FLAGS}")
    IF ( ${VENDOR}_LINKER_FLAGS)
        SET_TARGET_PROPERTIES(flexiblas_${ivendor} PROPERTIES LINK_FLAGS "${${VENDOR}_LINKER_FLAGS}")
        SET(${VENDOR}_BLAS_LINKER_FLAGS "${${VENDOR}_LINKER_FLAGS}" PARENT_SCOPE)
    ENDIF()

    IF (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
        SET(BLAS_LIBRARIES ${BLAS_LIBRARIES} gfortran)
    ENDIF()

    TARGET_LINK_LIBRARIES(flexiblas_${ivendor} ${${VENDOR}_LIBRARY})
    INSTALL(TARGETS flexiblas_${ivendor} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/${FLEXIBLAS_LIBRARY_DIR})

    LIST(APPEND EXTRA_BLAS "${VENDOR}")
    SET(${VENDOR}_BLAS_LIBRARIES "${${VENDOR}_LIBRARY}" PARENT_SCOPE)
    IF (NOT EXTRA_FLAGS)
        SET(${VENDOR}_BLAS_EXTRA_FLAGS "")
    ELSE()
        SET(${VENDOR}_BLAS_EXTRA_FLAGS "${EXTRA_FLAGS}" PARENT_SCOPE)
    ENDIF()

    UNSET(LIBNAME CACHE)
    SET(LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}flexiblas_${ivendor}${CMAKE_SHARED_LIBRARY_SUFFIX} ")
    FILE(WRITE "${CMAKE_BINARY_DIR}/${FLEXIBLAS_RC_DIR}/${VENDOR}.conf" "[${VENDOR}]\nlibrary = ${LIBNAME}\n\n")
    INSTALL(FILES "${CMAKE_BINARY_DIR}/${FLEXIBLAS_RC_DIR}/${VENDOR}.conf" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/${FLEXIBLAS_RC_DIR}")
    # Check for default setting
    STRING (TOLOWER  "${FLEXIBLAS_DEFAULT}" FDB_LOW)
    IF ( FDB_LOW STREQUAL ivendor)
        SET(DEFAULT_FOUND TRUE)
    ENDIF()
ENDMACRO()

MACRO(BuildFindPackage VENDOR BACKEND_CODE)
    FIND_PACKAGE(${VENDOR})
    IF ( ${VENDOR}_FOUND AND NOT "${${VENDOR}}" STREQUAL "OFF" )
    	MESSAGE(STATUS "Build BLAS interface: ${VENDOR}")
        MESSAGE(STATUS "Libs: ${${VENDOR}_LIBRARY}")
        BuildBackendBlas(${VENDOR} ${BACKEND_CODE})
    ELSEIF(NOT ${VENDOR}_FOUND)
        MESSAGE(STATUS "${VENDOR} not found.")
    ELSE()
        MESSAGE(STATUS "Found ${VENDOR} but deactivated manually.")
    ENDIF()
ENDMACRO()



MACRO(Build_Extra_BLAS VENDOR BACKEND_CODE)
	MESSAGE(STATUS "")
	UNSET(BLAS_FOUND CACHE)
	SET(BLAS_FOUND FALSE )
	UNSET(BLAS_LIBRARIES CACHE)
	UNSET(BLAS_LINKER_FLAGS CACHE)
	SET(BLA_VENDOR ${VENDOR})
	STRING(TOUPPER ${VENDOR} uvendor)
	IF( "${uvendor}" STREQUAL "APPLE")
		SET (uvendor APPLEACCELERATE)
	ENDIF()
	IF (DEFINED ${uvendor})
		IF (${uvendor} STREQUAL OFF)
			SET(BLAS_FOUND OFF)
			MESSAGE(STATUS "Disable BLAS backend - ${VENDOR}")
		ELSE()
			MESSAGE(STATUS "Use user defined settings for ${VENDOR}")
			SET(BLAS_FOUND TRUE)
			SET(BLAS_LIBRARIES ${${uvendor}})
			IF ( DEFINED ${uvendor}_LDFLAGS )
				SET(BLAS_LINKER_FLAGS ${${uvendor}_LDFLAGS})
			ENDIF()
		ENDIF()
	ELSE ()
		MESSAGE(STATUS "Search for ${VENDOR}")
		IF (INTEGER8 STREQUAL ON)
			FIND_PACKAGE(BLAS64)
		ELSE()
			FIND_PACKAGE(BLAS)
		ENDIF()
	ENDIF()
	IF (BLAS_FOUND)
		MESSAGE(STATUS "Build extra BLAS interface: ${VENDOR}")
		MESSAGE(STATUS "Libs: ${BLAS_LIBRARIES}")

		CheckBlasZdotcMKL("${BLAS_LIBRARIES}" "${BLAS_LINKER_FLAGS}" ${INTEGER8})
		SET(__CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
		SET(CMAKE_REQUIRED_LIBRARIES ${BLAS_LIBRARIES} ${BLAS_LINKER_FLAGS})
		#UNSET(SCABS1_EXIST CACHE)
		UNSET(ISFLEXIBLAS CACHE)
		UNSET(DAXPY CACHE)
		UNSET(MKL_OMATCOPY CACHE)
		UNSET(CBLAS_DAXPY CACHE)
		Check_Fortran_Function_Exists(SCABS1 SCABS1_EXIST)
		Check_Function_Exists(flexiblas_exit ISFLEXIBLAS)
		Check_Fortran_Function_Exists(DAXPY  DAXPY)
		Check_Fortran_Function_Exists(MKL_DOMATCOPY MKL_OMATCOPY)
		Check_Function_Exists(cblas_daxpy  CBLAS_DAXPY)
		SET(CMAKE_REQUIRED_LIBRARIES ${__CMAKE_REQUIRED_LIBRARIES})
		IF(NOT DAXPY)
			MESSAGE(FATAL_ERROR "Provided BLAS library does not contain a BLAS implementation or does not link.")
		ENDIF()

		IF (NOT ISFLEXIBLAS)
			UNSET(EXTRA_FLAGS CACHE)
			string(TOLOWER ${VENDOR} ivendor)
			string(TOUPPER ${VENDOR} uvendor)
			ADD_LIBRARY(flexiblas_${ivendor} SHARED ${BACKEND_CODE})
			IF (INTEGER8 STREQUAL ON OR BLAS_INTERFACE64)
				SET(EXTRA_FLAGS "-DBACKEND_INTEGER8")
			ELSE ()
				SET(EXTRA_FLAGS "")
			ENDIF()
			IF (ZDOTC_MKL)
				MESSAGE(STATUS "${VENDOR} uses Intel ZDOTC")
				SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DZDOTC_MKL")
			ENDIF (ZDOTC_MKL)
			IF (NOT SCABS1_EXIST)
				MESSAGE(STATUS "${VENDOR} does not provide a scabs1 function")
				SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DSCABS_MISSING")
			ENDIF(NOT SCABS1_EXIST)
			IF(CBLAS_DAXPY)
				IF (CBLAS STREQUAL ON)
					MESSAGE(STATUS "Add CBLAS in dummy library")
					SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DCBLAS_INTERFACE")
				ENDIF()
			ENDIF()

			#IF ( MKL_OMATCOPY )
			#	MESSAGE(STATUS "BLAS ${ivendor}$ seem to be an Intel MKL")
			#		SET_TARGET_PROPERTIES(blas_${ivendor} PROPERTIES COMPILE_DEFINITIONS "MKL")
			#ENDIF()
			MESSAGE(STATUS "Extra Linker Flags: ${BLAS_LINKER_FLAGS}")
			SET_TARGET_PROPERTIES(flexiblas_${ivendor} PROPERTIES COMPILE_FLAGS "${EXTRA_FLAGS}")
			# SET_TARGET_PROPERTIES(blas_${ivendor} PROPERTIES COMPILE_FLAGS "${EXTRA_FLAGS}" LINK_FLAGS "${BLAS_LINKER_FLAGS}")

			IF (CMAKE_C_COMPILER_ID STREQUAL "GNU")
				SET(BLAS_LIBRARIES ${BLAS_LIBRARIES} gfortran)
			ENDIF()
			TARGET_LINK_LIBRARIES(flexiblas_${ivendor} ${BLAS_LIBRARIES})
			INSTALL(TARGETS flexiblas_${ivendor} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/${FLEXIBLAS_LIBRARY_DIR})

			LIST(APPEND EXTRA_BLAS "${uvendor}")
			SET(${uvendor}_BLAS_LIBRARIES "${BLAS_LIBRARIES}" PARENT_SCOPE)
			IF (NOT EXTRA_FLAGS)
				SET(${uvendor}_BLAS_EXTRA_FLAGS "")
			ELSE()
				SET(${uvendor}_BLAS_EXTRA_FLAGS "${EXTRA_FLAGS}" PARENT_SCOPE)
			ENDIF()
			SET(${uvendor}_BLAS_LINKER_FLAGS "${BLAS_LINKER_FLAGS}" PARENT_SCOPE)

			UNSET(LIBNAME CACHE)
			SET(LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}flexiblas_${ivendor}${CMAKE_SHARED_LIBRARY_SUFFIX} ")
            FILE(WRITE "${CMAKE_BINARY_DIR}/${FLEXIBLAS_RC_DIR}/${VENDOR}.conf" "[${VENDOR}]\nlibrary = ${LIBNAME}\n\n")
            INSTALL(FILES "${CMAKE_BINARY_DIR}/${FLEXIBLAS_RC_DIR}/${VENDOR}.conf" DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/${FLEXIBLAS_RC_DIR}")
            # Check for default setting
            STRING (TOLOWER  "${FLEXIBLAS_DEFAULT}" FDB_LOW)
            IF ( FDB_LOW STREQUAL ivendor)
                SET(DEFAULT_FOUND TRUE)
            ENDIF()
		ELSE ()
			MESSAGE(STATUS "Skip BLAS ${ivendor} because it seems to contain FlexiBLAS")
		ENDIF()
	ENDIF()
ENDMACRO()

#
# Build BLAS interfaces
#
FILE(WRITE "${CMAKE_BINARY_DIR}/${FLEXIBLASRC}" "verbose = 0\n\n[NETLIB]\nlibrary = libflexiblas_netlib${CMAKE_SHARED_LIBRARY_SUFFIX}\n\n")

#
# Build Additional BLAS interfaces
#
#Build_Extra_BLAS(Generic)

SET(DEFAULT_FOUND FALSE)
IF (FLEXIBLAS_DEFAULT STREQUAL "NETLIB")
    SET(DEFAULT_FOUND TRUE)
ENDIF()

IF( BLAS_AUTO_DETECT STREQUAL ON)
IF (NOT INTEGER8)
    BuildFindPackage(OpenBLASSerial backends/generic/backend.c)
    BuildFindPackage(OpenBLASPThread backends/generic/backend.c)
    BuildFindPackage(OpenBLASOpenMP backends/generic/backend.c)

    BuildFindPackage(BlisSerial backends/generic/backend.c)
    BuildFindPackage(BlisPThread backends/generic/backend.c)
    BuildFindPackage(BlisOpenMP backends/generic/backend.c)

    BuildFindPackage(MklSerial backends/intel_mkl/backend.c)
    BuildFindPackage(MklOpenMP backends/intel_mkl/backend.c)
    BuildFindPackage(MklTBB backends/intel_mkl/backend.c)



ELSE()
    BuildFindPackage(OpenBLASSerial64 backends/generic/backend.c)
    BuildFindPackage(OpenBLASPThread64 backends/generic/backend.c)
    BuildFindPackage(OpenBLASOpenMP64 backends/generic/backend.c)

    BuildFindPackage(BlisSerial64 backends/generic/backend.c)
    BuildFindPackage(BlisPThread64 backends/generic/backend.c)
    BuildFindPackage(BlisOpenMP64 backends/generic/backend.c)

    BuildFindPackage(MklSerial64 backends/intel_mkl/backend.c)
    BuildFindPackage(MklOpenMP64 backends/intel_mkl/backend.c)
    BuildFindPackage(MklTBB64 backends/intel_mkl/backend.c)




ENDIF()

Build_Extra_BLAS(ATLAS  	backends/generic/backend.c)
Build_Extra_BLAS(Apple          backends/generic/backend.c)
ENDIF()

FOREACH(ADDITIONAL_BLAS ${EXTRA})
    MESSAGE(STATUS "Build additional BLAS backend with ${ADDITIONAL_BLAS}")
    IF (${ADDITIONAL_BLAS}_LIBRARY)
        BuildBackendBlas(${ADDITIONAL_BLAS} backends/generic/backend.c)
    ELSE()
        MESSAGE(FATAL_ERROR "-- ${ADDITIONAL_BLAS}_LIRBRAY missing.")
    ENDIF()
ENDFOREACH()


IF ( DEFAULT_FOUND )
    FILE(WRITE "${CMAKE_BINARY_DIR}/${FLEXIBLASRC}" "default = ${FLEXIBLAS_DEFAULT}\n\n")
ELSE()
    MESSAGE(STATUS "Default BLAS ${FLEXIBLAS_DEFAULT} not found. Use NETLIB instead.")
    SET(FLEXIBLAS_DEFAULT "NETLIB" PARENT_SCOPE)
    FILE(WRITE "${CMAKE_BINARY_DIR}/${FLEXIBLASRC}" "default = NETLIB\n\n")
ENDIF()

#
# MKL Custom
#
IF ( MKL_BUILDER STREQUAL ON)
	MESSAGE(STATUS "Build custom MKL from MKLROOT = $ENV{MKLROOT}")
	IF(NOT DEFINED ENV{MKLROOT})
		MESSAGE(FATAL_ERROR "MKLROOT must be set when building MKL backends.")
	ENDIF()
	EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )
	IF(${ARCHITECTURE} STREQUAL "x86_64")
		IF (INTEGER8 STREQUAL ON)
			SET(MKL_INTERFACE ilp64)
		ELSE()
			SET(MKL_INTERFACE lp64)
		ENDIF()
		SET(MKL_TARGET libintel64)
	ELSE()
		IF (INTEGER8 STREQUAL ON)
			SET(MKL_INTERFACE ilp64)
		ELSE()
			SET(MKL_INTERFACE lp64)
		ENDIF()
		SET(MKL_TARGET libia32)
	ENDIF()
	SET (MKL_LIST mkl_2018.3.list)
	ADD_CUSTOM_TARGET(mkl_parallel COMMAND make -C "$ENV{MKLROOT}/tools/builder" ${MKL_TARGET} export=${CMAKE_CURRENT_SOURCE_DIR}/backends/intel_mkl/${MKL_LIST} name="${CMAKE_BINARY_DIR}/libflexiblas_mkl_custom_parallel" threading=parallel interface=${MKL_INTERFACE})
	ADD_CUSTOM_TARGET(mkl_sequential COMMAND make -C "$ENV{MKLROOT}/tools/builder" ${MKL_TARGET} export=${CMAKE_CURRENT_SOURCE_DIR}/backends/intel_mkl/${MKL_LIST} name="${CMAKE_BINARY_DIR}/libflexiblas_mkl_custom_sequential" threading=parallel interface=${MKL_INTERFACE})
	SET(MKL_PARALLEL ${CMAKE_BINARY_DIR}/libflexiblas_mkl_custom_parallel.so)
	SET(MKL_SEQUENTIAL ${CMAKE_BINARY_DIR}/libflexiblas_mkl_custom_sequential.so)

	ADD_LIBRARY(flexiblas_intel_mkl SHARED backends/intel_mkl/backend.c)
	ADD_LIBRARY(flexiblas_intel_mkl_seq SHARED backends/intel_mkl/backend.c)

	IF (INTEGER8 STREQUAL ON OR BLAS_INTERFACE64)
        SET(EXTRA_FLAGS "-DMKL_BUILDER -DBACKEND_INTEGER8")
	ELSE ()
        SET(EXTRA_FLAGS "-DMKL_BUILDER")
	ENDIF()
	SET(EXTRA_FLAGS "${EXTRA_FLAGS} -DZDOTC_MKL")
	SET_TARGET_PROPERTIES(flexiblas_intel_mkl PROPERTIES COMPILE_FLAGS "${EXTRA_FLAGS}")
	SET_TARGET_PROPERTIES(flexiblas_intel_mkl_seq PROPERTIES COMPILE_FLAGS "${EXTRA_FLAGS}")
	TARGET_LINK_LIBRARIES(flexiblas_intel_mkl ${MKL_PARALLEL})
	TARGET_LINK_LIBRARIES(flexiblas_intel_mkl_seq ${MKL_SEQUENTIAL})
	ADD_DEPENDENCIES(flexiblas_intel_mkl mkl_parallel)
	ADD_DEPENDENCIES(flexiblas_intel_mkl_seq mkl_sequential)

	LIST(APPEND EXTRA_BLAS "INTEL_MKL")
	LIST(APPEND EXTRA_BLAS "INTEL_MKL_SEQ")

    SET(INTEL_MKL_BLAS_LIBRARIES "flexiblas_intel_mkl" PARENT_SCOPE)
    SET(INTEL_MKL_SEQ_BLAS_LIBRARIES "flexiblas_intel_mkl_seq" PARENT_SCOPE)



	SET(LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}flexiblas_intel_mkl${CMAKE_SHARED_LIBRARY_SUFFIX} ")
	FILE(APPEND "${CMAKE_BINARY_DIR}/${FLEXIBLASRC}" "[INTEL_MKL]\nlibrary = ${LIBNAME}\n\n")
	SET(LIBNAME "${CMAKE_SHARED_LIBRARY_PREFIX}flexiblas_intel_mkl_seq${CMAKE_SHARED_LIBRARY_SUFFIX} ")
	FILE(APPEND "${CMAKE_BINARY_DIR}/${FLEXIBLASRC}" "[INTEL_MKL_SEQ]\nlibrary = ${LIBNAME}\n\n")

	INSTALL(TARGETS flexiblas_intel_mkl LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/${FLEXIBLAS_LIBRARY_DIR})
	INSTALL(TARGETS flexiblas_intel_mkl_seq LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/${FLEXIBLAS_LIBRARY_DIR})
	INSTALL(FILES ${MKL_PARALLEL} ${MKL_SEQUENTIAL} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})


ENDIF()

# Compile Hooks
IF( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/hooks" )
    MESSAGE(STATUS "Found hook directory.")
    ADD_SUBDIRECTORY(hooks)
ENDIF()

#Build_Extra_BLAS(Generic)
SET(EXTRA_BLAS "${EXTRA_BLAS}" PARENT_SCOPE)
#SET(EXTRA_BLAS_VENDOR "${EXTRA_BLAS_VENDOR}" PARENT_SCOPE)



