set(_WASM_TOOLCHAIN_SUFFIX "")
if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
  set(_WASM_TOOLCHAIN_SUFFIX .exe)
endif()

set(_WASM_TOOLCHAIN_PREFIX "")
if (CONFIG_LLVM_ROOT)
  set(_WASM_TOOLCHAIN_PREFIX "${CONFIG_LLVM_ROOT}/bin")
else ()
  if (NOT (CMAKE_C_COMPILER OR CMAKE_CXX_COMPILER))
    find_program(CMAKE_C_COMPILER clang${_WASM_TOOLCHAIN_SUFFIX} NO_CACHE)
    find_program(CMAKE_CXX_COMPILER clang++${_WASM_TOOLCHAIN_SUFFIX} NO_CACHE)
  endif ()
  if (CMAKE_C_COMPILER)
    get_filename_component(_WASM_TOOLCHAIN_PREFIX "${CMAKE_C_COMPILER}" DIRECTORY)
  elseif (CMAKE_CXX_COMPILER)
    get_filename_component(_WASM_TOOLCHAIN_PREFIX "${CMAKE_CXX_COMPILER}" DIRECTORY)
  else ()
    set(CMAKE_C_COMPILER "${CONFIG_BUILD_C_COMPILER}")
    set(CMAKE_CXX_COMPILER "${CONFIG_BUILD_CXX_COMPILER}")
  endif ()
endif ()

if (_WASM_TOOLCHAIN_PREFIX)
  set(_WASM_TOOLCHAIN_PREFIX "${_WASM_TOOLCHAIN_PREFIX}/")
endif ()

set(CMAKE_C_COMPILER   "${_WASM_TOOLCHAIN_PREFIX}clang${_WASM_TOOLCHAIN_SUFFIX}"        CACHE FILEPATH "c")
set(CMAKE_CXX_COMPILER "${_WASM_TOOLCHAIN_PREFIX}clang++${_WASM_TOOLCHAIN_SUFFIX}"      CACHE FILEPATH "c++")
set(CMAKE_AR           "${_WASM_TOOLCHAIN_PREFIX}llvm-ar${_WASM_TOOLCHAIN_SUFFIX}"      CACHE FILEPATH "ar")
set(CMAKE_RANLIB       "${_WASM_TOOLCHAIN_PREFIX}llvm-ranlib${_WASM_TOOLCHAIN_SUFFIX}"  CACHE FILEPATH "ranlib")
set(CMAKE_LINKER       "${_WASM_TOOLCHAIN_PREFIX}wasm-ld${_WASM_TOOLCHAIN_SUFFIX}"      CACHE FILEPATH "linker")
set(CMAKE_NM           "${_WASM_TOOLCHAIN_PREFIX}llvm-nm${_WASM_TOOLCHAIN_SUFFIX}"      CACHE FILEPATH "nm")
set(CMAKE_OBJCOPY      "${_WASM_TOOLCHAIN_PREFIX}llvm-objcopy${_WASM_TOOLCHAIN_SUFFIX}" CACHE FILEPATH "objcopy")
set(CMAKE_OBJDUMP      "${_WASM_TOOLCHAIN_PREFIX}llvm-objdump${_WASM_TOOLCHAIN_SUFFIX}" CACHE FILEPATH "objdump")
set(CMAKE_STRIP        "${_WASM_TOOLCHAIN_PREFIX}llvm-strip${_WASM_TOOLCHAIN_SUFFIX}"   CACHE FILEPATH "strip")
set(LLVM_LLC           "${_WASM_TOOLCHAIN_PREFIX}llc${_WASM_TOOLCHAIN_SUFFIX}"          CACHE FILEPATH "llc")

set(CMAKE_ASM_COMPILER_ID_RUN TRUE)
set(CMAKE_ASM_COMPILER_ID  "Clang")
set(CMAKE_ASM_COMPILER_FORCED TRUE)

set(CMAKE_C_COMPILER_ID_RUN TRUE)
set(CMAKE_C_COMPILER_ID  "Clang")
set(CMAKE_C_COMPILER_FORCED TRUE)

set(CMAKE_CXX_COMPILER_ID_RUN TRUE)
set(CMAKE_CXX_COMPILER_ID  "Clang")
set(CMAKE_CXX_COMPILER_FORCED TRUE)

set(CMAKE_CXX17_COMPILE_FEATURES cxx_std_17)
set(CMAKE_CXX_COMPILE_FEATURES
  ${CMAKE_CXX17_COMPILE_FEATURES}
  )

set(CMAKE_C_COMPILER_TARGET   ${WASMUX_TARGET_TRIPLET})
set(CMAKE_CXX_COMPILER_TARGET ${WASMUX_TARGET_TRIPLET})
set(CMAKE_ASM_COMPILER_TARGET ${WASMUX_TARGET_TRIPLET})

set(_WASMUX_COMPILER_FLAGS
  --target=${WASMUX_TARGET_TRIPLET}
  -matomics
  -mmultivalue
  -mbulk-memory
  )

if (CONFIG_NO_STDLIB)
  list(APPEND _WASMUX_COMPILER_FLAGS --no-standard-libraries)
endif ()

set(_WASM_OBJECT_FLAGS "")

if (CONFIG_ENABLE_EH)
  list(APPEND _WASM_OBJECT_FLAGS "-mllvm -wasm-enable-eh")
endif ()

if (CONFIG_ENABLE_SJLJ)
  list(APPEND _WASM_OBJECT_FLAGS "-mllvm -wasm-enable-sjlj")
endif ()

if (CONFIG_ENABLE_EMSCRIPTEN_SJLJ)
  list(APPEND _WASM_OBJECT_FLAGS "-mllvm -enable-emscripten-sjlj")
endif ()

if (CONFIG_ENABLE_EMSCRIPTEN_CXX_EXCEPTIONS)
  list(APPEND _WASM_OBJECT_FLAGS "-mllvm -enable-emscripten-cxx-exceptions")
endif ()

if (CMAKE_SYSTEM_NAME STREQUAL Linux)
  list(APPEND _WASMUX_COMPILER_FLAGS -D__linux__)
endif ()

set(_WASMUX_ASM_FLAGS
  ${_WASMUX_COMPILER_FLAGS}
  )

set(_WASMUX_C_FLAGS
  ${_WASMUX_COMPILER_FLAGS}
  -O3
  )

set(_WASMUX_CXX_FLAGS
  ${_WASMUX_COMPILER_FLAGS}
  -O3
  )

set(_WASMUX_SHARED_LINKER_FLAGS
  -mexec-model=reactor
  -Wl,--no-entry
  )

set(_WASM_EXE_LINKER_FLAGS
  )

if (CONFIG_NO_START_FILES)
  list(APPEND _WASM_EXE_LINKER_FLAGS -nostartfiles)
endif ()

if (CONFIG_NO_ENTRY)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--no-entry)
endif ()

if (NOT DEFINED WASMUX_IMPORT_MEMORY)
  set(WASMUX_IMPORT_MEMORY ${WASMUX_IMPORT_MEMORY_DEFAULT})
endif ()

if (WASMUX_IMPORT_MEMORY)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--import-memory)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--import-memory)
endif ()

if (NOT DEFINED WASMUX_EXPORT_MEMORY)
  set(WASMUX_EXPORT_MEMORY ${WASMUX_EXPORT_MEMORY_DEFAULT})
endif ()

if (WASMUX_EXPORT_MEMORY)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--export-memory)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--export-memory)
endif ()

if (CONFIG_EXPORT_DYNAMIC)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--export-dynamic)
endif ()

if (NOT DEFINED WASMUX_SHARED_MEMORY)
  set(WASMUX_SHARED_MEMORY ${WASMUX_SHARED_MEMORY_DEFAULT})
endif ()

if (WASMUX_SHARED_MEMORY)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--shared-memory)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--shared-memory)
endif ()

if (CONFIG_MAX_MEMORY)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--max-memory=${CONFIG_MAX_MEMORY})
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--max-memory=${CONFIG_MAX_MEMORY})
endif ()

if (CONFIG_NODEFAULTLIBS)
  list(APPEND _WASM_EXE_LINKER_FLAGS -nodefaultlibs)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -nodefaultlibs)
endif ()

if (CONFIG_STACK_FIRST)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--stack-first)
endif ()

if (CONFIG_STACK_SIZE)
  list(APPEND _WASM_EXE_LINKER_FLAGS -z stack-size=${CONFIG_STACK_SIZE})
endif ()

if (CONFIG_GLOBAL_BASE)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--global-base=${CONFIG_GLOBAL_BASE})
endif ()

if (CONFIG_NO_GC_SECTIONS)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--no-gc-sections)
endif ()

if (NOT DEFINED WASMUX_RTLIB)
  set(WASMUX_RTLIB ${WASMUX_RTLIB_DEFAULT})
endif ()

if (WASMUX_RTLIB)
  list(APPEND _WASM_EXE_LINKER_FLAGS -rtlib=${WASMUX_RTLIB})
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -rtlib=${WASMUX_RTLIB})
endif ()

if (NOT DEFINED WASMUX_LTO)
  set(WASMUX_LTO ${WASMUX_LTO_DEFAULT})
endif ()

if (WASMUX_LTO)
  list(APPEND _WASMUX_CXX_FLAGS -flto)
  list(APPEND _WASM_EXE_LINKER_FLAGS -Wl,--lto-O3)
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS -Wl,--lto-O3)
endif ()

if (NOT DEFINED WASMUX_USE_FIND_UNIX_PATHS)
  set(WASMUX_USE_FIND_UNIX_PATHS ${WASMUX_USE_FIND_UNIX_PATHS_DEFAULT})
endif ()

if (WASMUX_USE_FIND_UNIX_PATHS)
  list(APPEND _WASMUX_C_FLAGS "--include-directory=${CMAKE_SYSROOT}/usr/include")
  list(APPEND _WASMUX_CXX_FLAGS "--include-directory=${CMAKE_SYSROOT}/usr/include")
  list(APPEND _WASM_EXE_LINKER_FLAGS "--library-directory=${CMAKE_SYSROOT}/usr/lib")
  list(APPEND _WASMUX_SHARED_LINKER_FLAGS "--library-directory=${CMAKE_SYSROOT}/usr/lib")
endif ()

string(REPLACE ";" " " _WASM_OBJECT_FLAGS "${_WASM_OBJECT_FLAGS}")
string(REPLACE ";" " " _WASMUX_ASM_FLAGS "${_WASMUX_ASM_FLAGS}")
string(REPLACE ";" " " _WASMUX_C_FLAGS "${_WASMUX_C_FLAGS}")
string(REPLACE ";" " " _WASMUX_CXX_FLAGS "${_WASMUX_CXX_FLAGS}")
string(REPLACE ";" " " _WASM_EXE_LINKER_FLAGS "${_WASM_EXE_LINKER_FLAGS}")
string(REPLACE ";" " " _WASMUX_SHARED_LINKER_FLAGS "${_WASMUX_SHARED_LINKER_FLAGS}")

set(CMAKE_ASM_FLAGS_INIT "${_WASMUX_ASM_FLAGS}")
set(CMAKE_C_FLAGS_INIT "${_WASMUX_C_FLAGS}")
set(CMAKE_CXX_FLAGS_INIT "${_WASMUX_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_INIT "${_WASM_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "${_WASMUX_SHARED_LINKER_FLAGS}")

set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${_WASM_OBJECT_FLAGS} -o <OBJECT> -c <SOURCE>")
set(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${_WASM_OBJECT_FLAGS} -o <OBJECT> -c <SOURCE>")

set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")

set(CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")

unset(_WASM_OBJECT_FLAGS)
unset(_WASMUX_COMPILER_FLAGS)
unset(_WASMUX_ASM_FLAGS)
unset(_WASMUX_C_FLAGS)
unset(_WASMUX_CXX_FLAGS)
unset(_WASM_EXE_LINKER_FLAGS)
unset(_WASMUX_SHARED_LINKER_FLAGS)

if (NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
endif()

if (NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
endif()

if (NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

if (NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()

set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SKIP_RPATH ON)
