# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("../public/mojo_sdk.gni")
import("//testing/test.gni")

# A mojo_edk_source_set is a mojo_sdk_source_set that does not restrict
# external dependencies and understands the following additional variables, all
# of which admit a list of the relevant elements specified relative to the
# location of the Mojo EDK:
# mojo_edk_configs
# allow_circular_mojo_edk_includes_from
# mojo_edk_public_deps
# mojo_edk_deps

# Note that it is assumed that the Mojo EDK is a sibling of the Mojo SDK in a
# client repo; the distinctions made above are for the sake of clarity in
# writing targets.
template("mojo_edk_source_set") {
  mojo_sdk_source_set(target_name) {
    if (defined(invoker.public_deps) || defined(invoker.deps)) {
      restrict_external_deps = false
    }

    if (defined(invoker.visibility)) {
      visibility = invoker.visibility
    }
    if (defined(invoker.mojo_edk_visibility)) {
      mojo_sdk_visibility = invoker.mojo_edk_visibility
    }
    if (defined(invoker.testonly)) {
      testonly = invoker.testonly
    }
    if (defined(invoker.sources)) {
      sources = invoker.sources
    }
    if (defined(invoker.defines)) {
      defines = invoker.defines
    }
    if (defined(invoker.public_configs)) {
      public_configs = invoker.public_configs
    }

    configs = []
    if (defined(invoker.configs)) {
      configs = invoker.configs
    }
    if (defined(invoker.mojo_edk_configs)) {
      foreach(edk_config, invoker.mojo_edk_configs) {
        # Check that the EDK config was not mistakenly given as an absolute
        # path.
        assert(get_path_info(edk_config, "abspath") != edk_config)
        configs += [ rebase_path(edk_config, ".", mojo_root) ]
      }
    }

    allow_circular_includes_from = []
    if (defined(invoker.allow_circular_includes_from)) {
      allow_circular_includes_from += invoker.allow_circular_includes_from
    }
    if (defined(invoker.allow_circular_mojo_edk_includes_from)) {
      foreach(edk_target, invoker.allow_circular_mojo_edk_includes_from) {
        # Check that the EDK target was not mistakenly given as an absolute
        # path.
        assert(get_path_info(edk_target, "abspath") != edk_target)
        allow_circular_includes_from +=
            [ rebase_path(edk_target, ".", mojo_root) ]
      }
    }

    if (defined(invoker.public_deps)) {
      public_deps = invoker.public_deps
    }
    mojo_sdk_public_deps = []
    if (defined(invoker.mojo_edk_public_deps)) {
      # The EDK is required to be a sibling of the SDK, so the relative
      # dependencies are rewritten in the same way.
      mojo_sdk_public_deps = invoker.mojo_edk_public_deps
    }
    if (defined(invoker.mojo_sdk_public_deps)) {
      mojo_sdk_public_deps += invoker.mojo_sdk_public_deps
    }

    if (defined(invoker.deps)) {
      deps = invoker.deps
    }
    mojo_sdk_deps = []
    if (defined(invoker.mojo_edk_deps)) {
      # The EDK is required to be a sibling of the SDK, so the relative
      # dependencies are rewritten in the same way.
      mojo_sdk_deps = invoker.mojo_edk_deps
    }
    if (defined(invoker.mojo_sdk_deps)) {
      mojo_sdk_deps += invoker.mojo_sdk_deps
    }
  }
}

template("mojo_edk_unittests") {
  test(target_name) {
    deps = [
      rebase_path("mojo/edk/system/test:run_all_unittests", ".", mojo_root),
    ]
    if (defined(invoker.sources)) {
      sources = invoker.sources
    }
    if (defined(invoker.deps)) {
      foreach(dep, invoker.deps) {
        # The only deps that are not specified relative to the location of the
        # Mojo EDK should be on targets within the same file or on a whitelisted
        # set of external dependencies.
        # TODO(vtl): Get rid of //base dependencies (and stop allowing it).
        assert(get_path_info(dep, "dir") == "." || dep == "//testing/gtest" ||
               dep == "//base")
        deps += [ dep ]
      }
    }
    if (defined(invoker.mojo_sdk_deps)) {
      foreach(sdk_dep, invoker.mojo_sdk_deps) {
        # Check that the SDK dep was not mistakenly given as an absolute path.
        assert(get_path_info(sdk_dep, "abspath") != sdk_dep)
        deps += [ rebase_path(sdk_dep, ".", mojo_root) ]
      }
    }
    if (defined(invoker.mojo_edk_deps)) {
      foreach(edk_dep, invoker.mojo_edk_deps) {
        # Check that the EDK dep was not mistakenly given as an absolute path.
        assert(get_path_info(edk_dep, "abspath") != edk_dep)
        deps += [ rebase_path(edk_dep, ".", mojo_root) ]
      }
    }
  }
}

template("mojo_edk_perftests") {
  test(target_name) {
    deps = [
      rebase_path("mojo/edk/system/test:run_all_perftests", ".", mojo_root),
    ]
    if (defined(invoker.sources)) {
      sources = invoker.sources
    }
    if (defined(invoker.deps)) {
      foreach(dep, invoker.deps) {
        # The only deps that are not specified relative to the location of the
        # Mojo EDK should be on targets within the same file or on a whitelisted
        # set of external dependencies.
        # TODO(vtl): Get rid of //base dependencies (and stop allowing it).
        assert(get_path_info(dep, "dir") == "." || dep == "//testing/gtest" ||
               dep == "//base")
        deps += [ dep ]
      }
    }
    if (defined(invoker.mojo_sdk_deps)) {
      foreach(sdk_dep, invoker.mojo_sdk_deps) {
        # Check that the SDK dep was not mistakenly given as an absolute path.
        assert(get_path_info(sdk_dep, "abspath") != sdk_dep)
        deps += [ rebase_path(sdk_dep, ".", mojo_root) ]
      }
    }
    if (defined(invoker.mojo_edk_deps)) {
      foreach(edk_dep, invoker.mojo_edk_deps) {
        # Check that the EDK dep was not mistakenly given as an absolute path.
        assert(get_path_info(edk_dep, "abspath") != edk_dep)
        deps += [ rebase_path(edk_dep, ".", mojo_root) ]
      }
    }
  }
}

# Build EDK things with static thread annotation analysis enabled.
# TODO(vtl): Should we set this at a higher level?
if (is_clang) {
  cflags = [ "-Wthread-safety" ]
}
