import openmp = liboneapi-openmp%libs{openmp}
import tbb    = liboneapi-tbb%libs{tbb}
import mpi    = liboneapi-mpi%libs{mpi}

# inter-dependencies

libs{mkl-thread-intel}: $openmp
{
  cxx.export.libs += $openmp
}

libs{mkl-thread-tbb}: $tbb
{
  cxx.export.libs += $tbb
}

libs{mkl-cluster-lp64-intelmpi}: $mpi
{
  cxx.export.libs += $mpi
}

libs{mkl-cluster-ilp64-intelmpi}: $mpi
{
  cxx.export.libs += $mpi
}

define [see_through] import: group

name = $string.replace($project, 'liboneapi-', '')

source redist.build

json{$name-manifest}: $src_root/manifest manifest.json

manifest_json = [json_object] $json.load($src_base/manifest.json)

package_infix = ($cc.target.class == 'windows' ? 'win' : 'lin')
package_ver   = "$(version.major).$(version.minor).$(version.patch)"

for plat: [json_object] ($manifest_json["$project"])
{
  plat_key   = $member_name($plat)
  plat_val   = $member_value($plat)
  enabled    = [bool] ($cc.target.cpu-$cc.target.class == $plat_key)
  devel_id   = [string] ($plat_val["devel_id"])
  runtime_id = [string] ($plat_val["runtime_id"])

  json{$devel_id...}:   json{$name-manifest}: include = (!$empty($devel_id))
  archive{$name-intel.oneapi.$(name).devel-$package_ver...}: json{$devel_id...}: include = (!$empty($devel_id) && $enabled)
  json{$runtime_id...}: json{$name-manifest}: include = (!$empty($runtime_id))
  archive{$name-intel.oneapi.$(name).runtime-$package_ver...}: json{$runtime_id...}: include = (!$empty($runtime_id) && $enabled)
}

extract{$name-devel}:   archive{$name-intel.oneapi.$(name).devel-$package_ver...}
extract{$name-runtime}: archive{$name-intel.oneapi.$(name).runtime-$package_ver...}

import{$name-headers}: extract{$name-devel}: update = match
import{$name-legals}: extract{$name-runtime}: update = match

import{$name-headers}:
{{
  o = $directory($>[0])
  d = $o/$name($>[0]).files

  hdrs = [paths]
  for g : $filter($<, group)
  {
    if test -d $o/$name($g)/include
    {
      find "$o/$name($g)/include" -type f -name "*.h*" \
        | set -n f [paths]
      hdrs += $f
    }
  }

  depdb dyndep \
    --dyn-target \
    --target-cwd "$o" \
    --target-what 'imported headers' \
    --target-extension-type 'h=h' \
    --target-extension-type 'hpp=hxx' \
    --format lines \
    --file $d \
    -- \
      echo $regex.merge($hdrs, '(.+)', '\1\n') >$d

  diag import $>

  for t : $filter_out($>, group)
  {
    touch $path($t)
  }
}}

import{$name-legals}:
{{
  o = $directory($>[0])
  d = $o/$name($>[0]).files

  files = [paths]
  for g : $filter($<, group)
  {
    if test -d $o/$name($g)/share/doc/$name/licensing
    {
      find "$o/$name($g)/share/doc/$name/licensing" -type f -name "*" \
        | set -n f [paths]
      files += $f
    }
  }

  depdb dyndep \
    --dyn-target \
    --target-cwd "$o" \
    --target-what 'imported legals' \
    --target-default-type 'legal' \
    --target-extension-type '=legal' \
    --format lines \
    --file $d \
    -- \
      echo $regex.merge($files, '(.+)', '\1\n') >$d

  diag import $>

  for t : $filter_out($>, group)
  {
    touch $path($t)
  }
}}

pub_hdrs = [strings] "-I$out_base/$name-devel/include/oneapi" "-I$out_base/$name-devel/include"

./: json{package}
json = [json_object] $json.load($src_base/package.json)
for plat: [json_object] ($json["platforms"])
{
  plat_key = $member_name($plat)
  enabled  = [bool] ($cc.target.cpu-$cc.target.class == $plat_key)
  plat_val = [json_object] $member_value($plat)

  for m: [json_object] ($plat_val["libs"])
  {
    n = $member_name($m)
    v = $member_value($m)

    ./: libs{$n}:
    {
      include = $enabled
      clean = false
    }

    # The "bundles" are either paired DLL + import lib (Windows),
    # or shared-only (implicitly loaded, just needs to respect RPATH).
    # Also explicitly append the extract-targets as inner-most prerequisites
    # to make sure they are always unpacked first.
    #
    [rule_hint=cxx.link] \
    libs{$n}: import{$name-legals} import{$name-headers}: \
                extract{$name-devel} extract{$name-runtime}:
    {
      include = $enabled
      update  = match
    }

    # Inter-dependencies
    #
    for d: [json_array] ($v["depends"])
    {
      dep = [name] $d
      libs{$n}: libs{$dep}: include = $enabled
      if $enabled
      {
        libs{$n}: cc.export.libs += libs{$dep}
      }
    }

    # Windows: paired DLL + import lib bundles.
    #
    for b: [json_array] ($v["linked"])
    {
      dll  = [path] $out_base/($b["dll"])
      libi = [paths]
      for x: [json_array] ($b["libs"])
        libi += [paths] $out_base/$x

      <libs{$dll} libi{$libi}>: extract{$name-devel} extract{$name-runtime}: include = $enabled
      libs{$n}: libs{$dll}: include = $enabled
      if $enabled
      {
        libs{$n}:
        {
          cc.export.libs =+ libs{$dll}
        }
      }
    }

    # Shared libs / runtime DLLs (no import lib).
    #
    loptions = [strings]
    for x: [json_array] ($v["loptions"])
      loptions += $x

    for so: [json_array] ($v["shared"])
    {
      s = [path] $out_base/$so
      <libs{$s}>: extract{$name-devel} extract{$name-runtime}: include = $enabled
      libs{$n}: libs{$s}: include = $enabled
      if $enabled
      {
        if ($cc.target.class != 'windows')
        {
          libs{$n}:
          {
            cc.export.libs =+ libs{$s} $loptions
          }
        }
      }
    }

    # Static libs.
    #
    for a: [json_array] ($v["archives"])
    {
      ar = [path] $out_base/$a
      <liba{$ar}>: extract{$name-devel}: include = $enabled
      libs{$n}: liba{$ar}: include = $enabled
      if $enabled
      {
        libs{$n}: cc.export.libs += liba{$ar}
      }
    }

    # Export options.
    #
    libs{$n}:
    {
      cc.type = cc
      cc.export.poptions = $pub_hdrs
    }

    # For pre-releases use the complete version to make sure they cannot
    # be used in place of another pre-release or the final version. See
    # the version module for details on the version.* variable values.
    #
    if $version.pre_release
      lib{$name}: bin.lib.version = "-$version.project_id"
    else
      lib{$name}: bin.lib.version = "-$version.major.$version.minor"
  }

  for m: [json_object] ($plat_val["exes"])
  {
    v = [json_object] ($member_value($m))
    p = [string] ($v["path"])

    ./: exe{$(p)...}: include = $enabled
    exe{$(p)...}: extract{$name-devel} extract{$name-runtime}: include = $enabled

    exe{$(p)...}:
    {
      install.subdirs = true
    }

    for d2: [json_array] ($v["depends"])
    {
      dep = [name] $d2
      exe{$(p)...}: libs{$dep}:
      {
        include = $enabled
        clean = false
      }
    }
  }
}

# No registered rule matches a pre-built exe that has no source prerequisites
# and does not yet exist on disk. This ad-hoc regex pattern rule provides an
# explicit perform(update)/perform(clean) entry point for all path-qualified
# exe targets so build2 can attach the operation to them.
#
exe{~'/(.+)/'}:
{{
  diag import $> $<
  touch $path($>)
}}

# Recreate the upstream include/ hierarchy under, e.g., /usr/include/.
#
$name-devel/include/{h hxx}{*}:
{
  install         = include/
  install.subdirs = true
}
