cmake_minimum_required(VERSION 3.21...3.29 FATAL_ERROR)
if (BUILD_RCPP)
    set(CMAKE_OSX_DEPLOYMENT_TARGET "11" CACHE STRING "Target MacOS Version")
elseif (SKBUILD)
    set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
    set(X_VCPKG_APPLOCAL_DEPS_INSTALL ON)
endif ()
mark_as_advanced(CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# the settings below will be automatically configured by the rest of this script
project(PLANC C CXX)
set(LIBPLANC_MAJOR_VERSION 1)
set(LIBPLANC_MINOR_VERSION 0)
set(LIBPLANC_PATCH_VERSION 2)
set(LIBPLANC_VERSION "${LIBPLANC_MAJOR_VERSION}.${LIBPLANC_MINOR_VERSION}.${LIBPLANC_PATCH_VERSION}")
set(NMFLIB_MAJOR_VERSION 1)
set(NMFLIB_MINOR_VERSION 0)
set(NMFLIB_PATCH_VERSION 1)
set(NMFLIB_VERSION "${NMFLIB_MAJOR_VERSION}.${NMFLIB_MINOR_VERSION}.${NMFLIB_PATCH_VERSION}")
message("This is libplanc ${LIBPLANC_VERSION} containing component nmflib ${NMFLIB_VERSION}")
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(CheckIncludeFile)
include(CheckCXXCompilerFlag)
include(FetchContent)
include(ExternalProject)
include(CheckSymbolExists)
include(CheckCXXSymbolExists)
include(CheckCXXSourceRuns)
include(cmake/FindRModule.cmake)

# Adhere to GNU filesystem layout conventions
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
set(CMAKE_C_VISIBILITY_PRESET¶ ON)
set(CMAKE_CXX_VISIBILITY_PRESET¶ ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 99)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
separate_arguments(PASSTHROUGH_CONFIGURE_ARGS)

if (NOT (APPLE AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES arm64)) AND NOT (BUILD_RCPP AND NOT BUILD_SHARED_LIBS))
    find_package(OpenMP)
    if (OpenMP_CXX_FOUND)
        if (MSVC)
            set(OpenMP_CXX_FLAGS "-openmp:llvm")
        endif ()
        add_compile_options(${OpenMP_CXX_FLAGS})
        add_link_options(${OpenMP_CXX_FLAGS})
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE)
        add_compile_options("/clang:-fopenmp")
        add_link_options("libomp.lib")
    endif ()
endif ()

if (BUILD_RCPP)
    if (APPLE)
      set(CMAKE_PROGRAM_PATH /opt/R/${CMAKE_HOST_SYSTEM_PROCESSOR}/bin)
      set(CMAKE_LIBRARY_PATH /opt/R/${CMAKE_HOST_SYSTEM_PROCESSOR}/lib)
      set(CMAKE_INCLUDE_PATH /opt/R/${CMAKE_HOST_SYSTEM_PROCESSOR}/include)
    endif ()
    find_package(R REQUIRED)
    add_compile_definitions(USING_R)
    if (NOT BUILD_SHARED_LIBS)
        add_compile_options(${R_OPENMP_CXXFLAGS})
        add_link_options(${R_OPENMP_CXXFLAGS})
    elseif (OpenMP_CXX_FOUND)
        set(MKL_THREADING gnu_thread)
    else()
        set(MKL_THREADING sequential)
    endif()
    set(MKL_INTERFACE lp64)
    if(R_RHOME MATCHES "^/data/gannet/ripley/R/.*")
        set(BLA_VENDOR Generic)
    endif()
endif ()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT MSVC)
    execute_process(COMMAND clang -v ERROR_VARIABLE CLANGID)
    if(CLANGID)
    string(REGEX MATCH "\\(.*\\)" CLANGPARSE ${CLANGID})
    if (CLANGPARSE MATCHES "\\(CLANG\\: AOCC.*")
        set(BLA_VENDOR AOCL_mt)
        add_compile_options(-zopt -O3 -flto -fstrip-mining -freciprocal-math -finline-recursion=3
                -fremap-arrays -fnt-store=aggressive -mrecip=all -optimize-strided-mem-cost
                -fenable-aggressive-gather -favoid-fpe-causing-opt)
    endif ()
  endif ()
endif ()
find_package(MKL CONFIG)
if(MKL_DIR)
    set(CMAKE_REQUIRED_LIBRARIES MKL::MKL)
    set(CMAKE_REQUIRED_INCLUDES "${MKL_INCLUDE}")
    set(test_mkl_link "
#include <mkl_cblas.h>
int main() {
return 0;
}
")
    check_cxx_source_runs("${test_mkl_link}" MKL_LINKS)
    unset(CMAKE_REQUIRED_LIBRARIES)
    unset(CMAKE_REQUIRED_INCLUDES)
endif()
find_package(BLAS)
find_package(LAPACK)
find_package(OpenBLAS CONFIG)
if (MKL_DIR AND MKL_LINKS AND NOT BLA_VENDOR MATCHES "Generic")
    message(STATUS "found MKL")
    set(USING_MKL 1)
    unset(LAPACK_LIBRARIES)
    set(CBLAS_H_DIR "${MKL_INCLUDE}")
    add_compile_definitions("MKL_FOUND")
elseif ((BUILD_RCPP AND WIN32) OR (OpenBLAS_DIR AND NOT DEFINED BLA_VENDOR))
    find_package(OpenBLAS CONFIG REQUIRED)
    set(USING_OPENBLAS 1)
else ()
    find_package(BLAS REQUIRED)
    find_package(LAPACK REQUIRED)
    set(USING_BLAS 1)
endif ()

set(HIGHFIVE_EXAMPLES OFF CACHE INTERNAL BOOL)
set(HIGHFIVE_BUILD_DOCS OFF CACHE INTERNAL BOOL)
set(HIGHFIVE_USE_BOOST OFF CACHE INTERNAL BOOL)
set(HIGHFIVE_UNIT_TESTS OFF CACHE INTERNAL BOOL)
set(HIGHFIVE_HAS_CONCEPTS OFF CACHE INTERNAL BOOL)
if ((WIN32 OR APPLE) AND NOT DEFINED ENV{CONDA_BUILD})
    set(HDF5_USE_STATIC_LIBRARIES ON CACHE INTERNAL BOOL)
    set(HIGHFIVE_STATIC_HDF5 ON CACHE INTERNAL BOOL)
endif ()
FetchContent_Declare(
        HighFive
        URL https://github.com/BlueBrain/HighFive/archive/refs/tags/v3.0.0-beta2.tar.gz
        URL_HASH SHA256=E09BDF89DCEB3314928237A1B102FB760082C3C880C20854394E3AD2478F602D
)
FetchContent_Populate(HighFive)
FetchContent_GetProperties(HighFive SOURCE_DIR HighFive_SOURCE_DIR)
find_package(HDF5 REQUIRED COMPONENTS C)
set(HDF5_TARGET 1)
set(CMAKE_REQUIRED_LIBRARIES ${HDF5_LIBRARIES})
set(HighFive_Includes "${HighFive_SOURCE_DIR}/include" "${HDF5_INCLUDE_DIRS}")
set(CMAKE_REQUIRED_INCLUDES "${HighFive_Includes}")
set(test_hdf5_link "
#include <highfive/highfive.hpp>
int main() {
return 0;
}
")
check_cxx_source_runs("${test_hdf5_link}" HDF5_LINKS)
unset(CMAKE_REQUIRED_LIBRARIES)
unset(CMAKE_REQUIRED_INCLUDES)
if (NOT HDF5_LINKS)
    set(HDF5_TARGET 0)
    # from https://gitlab.kitware.com/cmake/cmake/-/issues/18872#note_1090297
    # Since there is no compiler line to help us, add the additional required
    # libraries manually.
    set(_additional_libs sz z dl m)
    foreach (_additional_lib IN LISTS _additional_libs)
        # If both static and shared are available, prefer static to avoid libdl
        # annoyances ("Using 'dlopen' in statically linked applications requires
        # at runtime the shared libraries from the glibc version used for
        # linking")
        if (HDF5_USE_STATIC_LIBRARIES)
            set(_libnames ${_additional_lib} lib${_additional_lib}.a)
        else ()
            set(_libnames ${_additional_lib})
        endif (HDF5_USE_STATIC_LIBRARIES)
        set(_libvar "LIB_${_additional_lib}")
        find_library(${_libvar}
                NAMES ${_libnames}
                HINTS ${HDF5_ROOT}
                PATH_SUFFIXES lib Lib
                REQUIRED)
        if (HDF5_FIND_DEBUG)
            message(STATUS "${_additional_lib} (${_libvar}): ${${_libvar}}")
        endif (HDF5_FIND_DEBUG)
        if (${${_libvar}} STREQUAL "${_libvar}-NOTFOUND")
            message(FATAL_ERROR "${_additional_lib} not found, required for HDF5 install")
        endif ()
        list(APPEND HDF5_LIBRARIES ${${_libvar}})
    endforeach ()
    list(REMOVE_DUPLICATES HDF5_LIBRARIES)
endif ()
add_library(utils OBJECT ${PROJECT_SOURCE_DIR}/common/utils.cpp)
target_include_directories(utils PUBLIC ${HighFive_Includes})

if (BUILD_RCPP)
    find_r_module(Rcpp)
    find_r_module(RcppArmadillo)
    find_r_module(RcppProgress)
    if (R_INCLUDE_DIR)
        include_directories("${R_INCLUDE_DIR}")
    else ()
        message(FATAL_ERROR "missing R headers")
    endif ()
    if (R_RCPP)
        include_directories("${R_RCPP}/include")
    else ()
        message(FATAL_ERROR "missing RcppArmadillo")
    endif ()
    if (R_RCPPARMADILLO)
        include_directories("${R_RCPPARMADILLO}/include")
    else ()
        message(FATAL_ERROR "missing RcppArmadillo")
    endif ()
    if (R_RCPPPROGRESS)
        include_directories("${R_RCPPPROGRESS}/include")
    else ()
        message(FATAL_ERROR "missing RcppProgress")
    endif ()
elseif (SKBUILD)
    find_package(Python REQUIRED COMPONENTS Interpreter Development.Module
            OPTIONAL_COMPONENTS Development.SABIModule)
    find_package(nanobind CONFIG REQUIRED)
    set(HEADER_ONLY CACHE INTERNAL BOOL ON)
    find_package(armadillo)
    if(NOT Armadillo_FOUND)
    FetchContent_Declare(
            armadillo
            URL https://phoenixnap.dl.sourceforge.net/project/arma/armadillo-14.0.1.tar.xz
            URL_HASH SHA256=8346F1E7567BCB3A28DD770097208E78D33A5D41E0A71AF2A7E7FD997F17DB44
    )
    FetchContent_Populate(armadillo)
    FetchContent_GetProperties(armadillo SOURCE_DIR armadillo_SOURCE_DIR)
    endif()
    find_package(indicators CONFIG REQUIRED)
    add_library(progressWrapper OBJECT ${PROJECT_SOURCE_DIR}/common/progressWrapper.cpp)
    target_link_libraries(progressWrapper PUBLIC indicators::indicators)
    target_include_directories(utils PUBLIC "${armadillo_SOURCE_DIR}/include")
    target_link_libraries(utils PUBLIC progressWrapper)
else ()
    find_package(Armadillo CONFIG REQUIRED)
    find_package(indicators CONFIG REQUIRED)
    add_library(progressWrapper OBJECT ${PROJECT_SOURCE_DIR}/common/progressWrapper.cpp)
    target_link_libraries(progressWrapper PUBLIC indicators::indicators)
    target_include_directories(utils PUBLIC ${ARMADILLO_INCLUDE_DIRS})
    target_link_libraries(utils PUBLIC progressWrapper)
endif ()

if (MSVC)
    check_cxx_compiler_flag("/fp:fast" MSVC_FAST_FLOAT)
    if (MSVC_FAST_FLOAT)
        add_compile_options("/fp:fast")
    endif ()
    if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64")
        check_cxx_compiler_flag("/arch:AVX" ARCH_AVX)
        if (ARCH_AVX)
            add_compile_options("/arch:AVX")
        endif ()
    elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64")
        check_cxx_compiler_flag("/arch:armv8.2" ARCH_ARM82)
        if (ARCH_ARM82)
            add_compile_options("/arch:armv8.2")
        endif ()
    endif ()
else ()
    check_cxx_compiler_flag("-funsafe-math-optimizations" UNSAFE_MATH)
    if (UNSAFE_MATH)
        add_compile_options("-funsafe-math-optimizations")
    endif ()
    check_cxx_compiler_flag("-ffinite-math-only" FINITE_MATH)
    if (FINITE_MATH)
        add_compile_options("-ffinite-math-only")
    endif ()
    check_cxx_compiler_flag("-fno-trapping-math" TRAPPING_MATH)
    if (TRAPPING_MATH)
        add_compile_options("-fno-trapping-math")
    endif ()
    check_cxx_compiler_flag("-fno-math-errno" ERRNO_MATH)
    if (ERRNO_MATH)
        add_compile_options("-fno-math-errno")
    endif ()
    check_cxx_compiler_flag("-fno-signed-zeros" UNSIGNED_ZERO)
    if (UNSIGNED_ZERO)
        add_compile_options("-fno-signed-zeros")
    endif ()
    check_cxx_compiler_flag("-freciprocal-math" RECIPROCAL_MATH)
    if (RECIPROCAL_MATH)
        add_compile_options("-freciprocal-math")
    endif ()
    if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64")
        check_cxx_compiler_flag("-mavx" ARCH_AVX)
        if (ARCH_AVX)
            add_compile_options("-mavx")
        endif ()
        check_cxx_compiler_flag("-mpopcnt" HAS_POPCNT)
        if (HAS_POPCNT)
            add_compile_options("-mpopcnt")
        endif ()
    endif ()
    if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64")
        check_cxx_compiler_flag("-march=armv8.2-a+simd" ARCH_ARM82)
        if (ARCH_ARM82)
            add_compile_options("-march=armv8.2-a+simd")
        endif ()
    endif ()
endif ()

if (NOT USING_OPENBLAS_H AND NOT USING_MKL)
    if (CBLAS_H_DIR)
        include_directories(BEFORE ${CBLAS_H_DIR})
    else ()
        set(CBLAS_H_DIR CACHE PATH "Directory containing cblas.h")
        check_include_file("cblas.h" CBLAS_HEADER)
        if (NOT CBLAS_HEADER)
            check_include_file("flexiblas/cblas.h" FLEXIBLAS_HEADER)
            if (FLEXIBLAS_HEADER)
                add_compile_definitions("HAVE_FLEXIBLAS_CBLAS_H")
            else ()
                #message(FATAL_ERROR "no cblas header, please set include directory with CBLAS_H_DIR variable")
            endif ()
        endif ()
    endif ()
endif ()


add_library(hw_detect OBJECT ${PROJECT_SOURCE_DIR}/common/hw_detect.c)

find_package(HWLOC)

if (HWLOC_FOUND)
    target_link_libraries(hw_detect PUBLIC "$<IF:$<BOOL:pkgcfg_lib_HWLOC_hwloc>,${pkgcfg_lib_HWLOC_hwloc},${HWLOC_LDFLAGS}>")
    target_include_directories(hw_detect PRIVATE "${HWLOC_INCLUDE_DIRS}")
elseif (MSVC)
    FetchContent_Declare(hwloc
            URL https://download.open-mpi.org/release/hwloc/v2.11/hwloc-2.11.2.tar.gz
            URL_HASH SHA256=866ac8ef07b350a6a2ba0c6826c37d78e8994dcbcd443bdd2b436350de19d540
            SOURCE_SUBDIR contrib/windows-cmake
    )
    set(HWLOC_ENABLE_TESTING INTERNAL BOOL OFF)
    set(HWLOC_SKIP_LSTOPO INTERNAL BOOL ON)
    set(HWLOC_SKIP_TOOLS INTERNAL BOOL ON)
    FetchContent_MakeAvailable(hwloc)
    target_link_libraries(hw_detect PUBLIC hwloc)
else ()
    set(cmd "sh")
    list(APPEND cmd ../hwloc/configure --with-pic --prefix=${hwloc_SOURCE_DIR}/out/ --disable-picky --enable-shared=no --enable-static=yes)
    list(APPEND cmd --disable-cairo --disable-libxml2 --disable-io --disable-plugin-dlopen --disable-plugin-ltdl --enable-embedded-mode)
    if (WIN32)
        if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES ARM64)
            list(APPEND cmd --build=aarch64-w64-mingw32)
            set(HWLOC_LD ld.lld)
        else ()
            list(APPEND cmd --build=x86_64-w64-mingw32)
            set(HWLOC_LD ld)
        endif ()
    elseif (PASSTHROUGH_CONFIGURE_ARGS)
        list(APPEND cmd ${PASSTHROUGH_CONFIGURE_ARGS})
    endif ()
    if (BUILD_RCPP)
        #if(WIN32)
        #    # prioritize Git Patch on Windows as other Patches may be very old and incompatible.
        #    #find_package(Git)
        #
        #    #if(Git_FOUND)
        #    #    get_filename_component(GIT_DIR ${GIT_EXECUTABLE} DIRECTORY)
        #    #    get_filename_component(GIT_DIR ${GIT_DIR} DIRECTORY)
        #    #endif()
        #endif()

        find_program(PATCH
                NAMES patch
                HINTS ${GIT_DIR}
                PATH_SUFFIXES usr/bin
        )
        file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/../../tools/patches/series" hwloc_patch_list)
        list(TRANSFORM hwloc_patch_list PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/../../tools/patches/")
        ExternalProject_Add(hwloc
                URL https://download.open-mpi.org/release/hwloc/v2.11/hwloc-2.11.2.tar.gz
                URL_HASH SHA256=866ac8ef07b350a6a2ba0c6826c37d78e8994dcbcd443bdd2b436350de19d540
                PATCH_COMMAND ${CMAKE_COMMAND} -E cat ${hwloc_patch_list} | ${PATCH} -p1 -l
                BUILD_BYPRODUCTS <BINARY_DIR>/hwloc/.libs/libhwloc_embedded.a
                CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env "LD=${HWLOC_LD}" "CFLAGS=-DNDEBUG $ENV{CFLAGS} $<$<BOOL:${APPLE}>:-mmacosx-version-min=11>" ${cmd} && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/aclocal.m4 && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/Makefile.in && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/configure && ${CMAKE_COMMAND} -E touch_nocreate config.status
        )
    else ()
        ExternalProject_Add(hwloc
                URL https://download.open-mpi.org/release/hwloc/v2.11/hwloc-2.11.2.tar.gz
                URL_HASH SHA256=866ac8ef07b350a6a2ba0c6826c37d78e8994dcbcd443bdd2b436350de19d540
                BUILD_BYPRODUCTS <BINARY_DIR>/hwloc/.libs/libhwloc_embedded.a
                CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env "CFLAGS=-DNDEBUG $ENV{CFLAGS} $<$<BOOL:${APPLE}>:-mmacosx-version-min=10.14>" ${cmd} && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/aclocal.m4 && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/Makefile.in && ${CMAKE_COMMAND} -E touch_nocreate ../hwloc/configure && ${CMAKE_COMMAND} -E touch_nocreate config.status
        )
    endif ()
    ExternalProject_Get_Property(hwloc SOURCE_DIR BINARY_DIR)
    set(HWLOC_LDFLAGS "${BINARY_DIR}/hwloc/.libs/libhwloc_embedded.a")
    unset(pkgcfg_lib_HWLOC_hwloc)
    target_include_directories(hw_detect PRIVATE "${BINARY_DIR}/include" "${SOURCE_DIR}/include")
    add_custom_command(TARGET hwloc POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E remove_directory ${SOURCE_DIR}/utils/lstopo
            VERBATIM)
    add_dependencies(hw_detect hwloc)
    target_link_libraries(hw_detect PRIVATE "${BINARY_DIR}/hwloc/.libs/libhwloc_embedded.a")
endif ()

add_library(detect_blas OBJECT ${PROJECT_SOURCE_DIR}/common/detect_blas.c)
check_include_file(dlfcn.h HAS_DLFCN)
if (WIN32 AND NOT HAS_DLFCN)
    find_package(dlfcn-win32 CONFIG REQUIRED)
    set(DLFCN_LINK 1)
endif ()
if (APPLE)
    set(HWLOC_FRAMEWORKS "-framework Foundation" "-framework IOKit" "-framework OpenCL")
endif ()

set(PLANC_COMMON ${PROJECT_SOURCE_DIR}/common)
set(NNLS_SRC ${PROJECT_SOURCE_DIR}/nnls)
set(NMF_SOURCE_DIR ${PROJECT_SOURCE_DIR}/nmf)
message(STATUS "NNLS_SOURCE_DIR =  ${NNLS_SRC}")
message(STATUS "NMF_SOURCE_DIR =  ${NMF_SOURCE_DIR}")
message(STATUS "NMFLIB_COMMON =  ${PLANC_COMMON}")

add_subdirectory(nmf)
target_link_libraries(nmflib PUBLIC "$<$<BOOL:${USING_MKL}>:MKL::MKL>" "$<$<BOOL:${USING_OPENBLAS}>:${OpenBLAS_LIBRARIES}>" "$<$<BOOL:${USING_BLAS}>:BLAS::BLAS>" "$<$<BOOL:${USING_BLAS}>:LAPACK::LAPACK>"
        "$<$<BOOL:${HWLOC_FRAMEWORKS}>:${HWLOC_FRAMEWORKS}>"
        "$<$<BOOL:${DLFCN_LINK}>:dlfcn-win332::dl>" "$<IF:$<BOOL:HDF5_TARGETc>,HDF5::HDF5,${HDF5_LIBRARIES}>" ${R_LDFLAGS} ${RCPP_FLIBS})

if (BUILD_RCPP)
    get_directory_property(CMAKE_DEFINES COMPILE_DEFINITIONS)
    list(TRANSFORM CMAKE_DEFINES PREPEND "-D")
    if(CBLAS_H_DIR)
    list(PREPEND CMAKE_DEFINES -I"${CBLAS_H_DIR}")
    endif()
    list(JOIN CMAKE_DEFINES " " CPPFLAGS)
    if (BUILD_SHARED_LIBS)
    if (APPLE)
    if (R_SHLIB_EXT MATCHES ".so")
    set_target_properties(nmflib PROPERTIES SUFFIX ${R_SHLIB_EXT})
    endif ()
    set(EXTRA_LD_ARGS "-rpath @loader_path/../libs")
    elseif (NOT WIN32)
    set(EXTRA_LD_ARGS  "'-Wl,-rpath,$$ORIGIN/../libs,--enable-new-dtags'")
    else ()
    set(EXTRA_LD_ARGS "")
    endif ()
    else ()
        if(APPLE AND ((CMAKE_HOST_SYSTEM_PROCESSOR MATCHES arm64) OR NOT OpenMP_CXX_FOUND))
            set(BLAS_LIBRARIES_EXTRACT '-L-framework -LAccelerate')
            unset(BLAS_LIBRARIES)
            unset(LAPACK_LIBRARIES)
        endif()
        set(EXTRA_LD_ARGS ${BLAS_LIBRARIES_EXTRACT} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} ${pkgcfg_lib_HWLOC_hwloc} ${HWLOC_LDFLAGS} "$<$<BOOL:${HWLOC_FRAMEWORKS}>:${HWLOC_FRAMEWORKS}>" ${HDF5_LIBRARIES} ${R_LDFLAGS} ${RCPP_FLIBS})
    list(JOIN EXTRA_LD_ARGS " " EXTRA_LD_ARGS)
    endif ()
    install(TARGETS nmflib RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../" ARCHIVE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../" LIBRARY DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../")
    configure_file(../Makevars.in ../Makevars.gen @ONLY NEWLINE_STYLE LF)
    file(GENERATE OUTPUT ../Makevars INPUT ../Makevars.gen NEWLINE_STYLE LF)
elseif (SKBUILD)
    nanobind_add_module(pyplanc STABLE_ABI NB_STATIC ${CMAKE_CURRENT_SOURCE_DIR}/python/pybind_interface.cpp)
    #target_include_directories(pyplanc PRIVATE "python")
    find_library(NMFLIB_LIB nmflib)
    if(NMFLIB_LIB)
        find_file(NMFLIB_INC nmflib_export.h HINTS $ENV{LIBRARY_INC} $ENV{PREFIX}/include PATH_SUFFIXES libplanc/nmf REQUIRED)
        get_target_property(NMFLIB_INC nmflib INCLUDE_DIRECTORIES)
#        if(WIN32)
#            find_package(CBLAS REQUIRED)
#        endif()
        target_include_directories(pyplanc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/nmf ${NMFLIB_INC})
        target_link_libraries(pyplanc PRIVATE utils progressWrapper ${NMFLIB_LIB})
    else()
        target_link_libraries(pyplanc PRIVATE nmflib)
        target_link_libraries(nmflib PUBLIC progressWrapper)
        install(TARGETS nmflib RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../" ARCHIVE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../" LIBRARY DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/../")
    endif()
    install(TARGETS pyplanc LIBRARY DESTINATION .)
else()
    install(TARGETS nmflib
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )
    set(nmf_headers nmf/nmf_lib.hpp common/data.hpp common/config.h common/detect_blas.h ${CMAKE_CURRENT_BINARY_DIR}/nmf/nmflib_export.h)
    set(nnls_headers nnls/nnls_lib.hpp)
    install(FILES ${nmf_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libplanc/nmf)
    install(FILES ${nnls_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libplanc/nnls)
endif()
if (BUILD_EXECUTABLE)
    add_executable(plancnmf nmf/nmf_cmd.cpp)
    find_package(argparse REQUIRED)
    target_link_libraries(nmflib PUBLIC progressWrapper)
    target_link_libraries(plancnmf PRIVATE nmflib argparse::argparse $<$<BOOL:${MINGW}>:detect_blas>)
    target_include_directories(plancnmf PRIVATE ${PLANC_COMMON} ${CMAKE_CURRENT_BINARY_DIR})
    install(TARGETS plancnmf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
else ()

endif ()
