# Copyright 2019 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("//build/config/ios/deployment_target.gni")

declare_args() {
  # Configure whether whole module optimization is enabled when compiling
  # swift modules.
  swift_whole_module_optimization = true
}

template("ios_toolchain") {
  toolchain(target_name) {
    assert(defined(invoker.toolchain_args),
           "Toolchains must declare toolchain_args")

    toolchain_args = {
      forward_variables_from(invoker.toolchain_args, "*")
    }

    _sdk_info = exec_script("//build/config/ios/scripts/sdk_info.py",
                            [
                              "--target-cpu",
                              current_cpu,
                              "--deployment-target",
                              ios_deployment_target,
                            ],
                            "json")

    cc = "clang -target ${_sdk_info.target} -isysroot ${_sdk_info.sdk_path}"
    cxx = "clang++ -target ${_sdk_info.target} -isysroot ${_sdk_info.sdk_path}"

    swiftmodule_switch = "-Wl,-add_ast_path,"

    tool("link") {
      output = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
      rspfile = output + ".rsp"
      rspfile_content = "{{inputs_newline}}"

      outputs = [ output ]
      command = "$cxx {{ldflags}} -o $output -Wl,-filelist,$rspfile {{libs}} {{solibs}} {{frameworks}} {{swiftmodules}}"
      description = "LINK {{output}}"

      default_output_dir = "{{root_out_dir}}"
      default_output_extension = ""
      output_prefix = ""
    }

    tool("solink") {
      dylib = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
      rspfile = dylib + ".rsp"
      rspfile_content = "{{inputs_newline}}"

      outputs = [ dylib ]
      command = "$cxx -dynamiclib {{ldflags}} -o $dylib -Wl,-filelist,$rspfile {{libs}} {{solibs}} {{frameworks}} {{swiftmodules}}"
      description = "SOLINK {{output}}"

      default_output_dir = "{{root_out_dir}}"
      default_output_extension = ".dylib"
      output_prefix = "lib"
    }

    tool("cc") {
      depfile = "{{output}}.d"
      precompiled_header_type = "gcc"
      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
      depsformat = "gcc"
      description = "CC {{output}}"
      outputs = [ "{{target_out_dir}}/{{label_name}}/{{source_name_part}}.o" ]
    }

    tool("cxx") {
      depfile = "{{output}}.d"
      precompiled_header_type = "gcc"
      command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
      depsformat = "gcc"
      description = "CXX {{output}}"
      outputs = [ "{{target_out_dir}}/{{label_name}}/{{source_name_part}}.o" ]
    }

    tool("objc") {
      depfile = "{{output}}.d"
      precompiled_header_type = "gcc"
      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
      depsformat = "gcc"
      description = "OBJC {{output}}"
      outputs = [ "{{target_out_dir}}/{{label_name}}/{{source_name_part}}.o" ]
    }

    tool("objcxx") {
      depfile = "{{output}}.d"
      precompiled_header_type = "gcc"
      command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{framework_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}"
      depsformat = "gcc"
      description = "OBJCXX {{output}}"
      outputs = [ "{{target_out_dir}}/{{label_name}}/{{source_name_part}}.o" ]
    }

    tool("stamp") {
      command = "touch {{output}}"
      description = "STAMP {{output}}"
    }

    tool("copy_bundle_data") {
      command = "rm -rf {{output}} && cp -PR {{source}} {{output}}"
      description = "COPY_BUNDLE_DATA {{output}}"
    }

    tool("swift") {
      depfile = "{{target_out_dir}}/{{module_name}}.d"
      depsformat = "gcc"

      outputs = [
        # The module needs to be the first output to ensure the
        # depfile generate works correctly with ninja < 1.9.0.
        "{{target_gen_dir}}/{{module_name}}.swiftmodule",

        "{{target_gen_dir}}/{{module_name}}.h",
        "{{target_gen_dir}}/{{module_name}}.swiftdoc",
        "{{target_gen_dir}}/{{module_name}}.swiftsourceinfo",
      ]

      if (swift_whole_module_optimization) {
        _extra_flag = "--whole-module-optimization"
        _object_dir = "{{target_out_dir}}"
        outputs += [ "{{target_out_dir}}/{{module_name}}.o" ]
      } else {
        _extra_flag = ""
        _object_dir = "{{target_out_dir}}/{{label_name}}"
        partial_outputs =
            [ "{{target_out_dir}}/{{label_name}}/{{source_name_part}}.o" ]
      }

      _swiftc = rebase_path("//build/toolchain/apple/swiftc.py", root_build_dir)
      command = "$_swiftc --target ${_sdk_info.target} --sdk ${_sdk_info.sdk_path} --module-name {{module_name}} --object-dir $_object_dir --module-path {{target_gen_dir}}/{{module_name}}.swiftmodule --header-path {{target_gen_dir}}/{{module_name}}.h --depfile {{target_out_dir}}/{{module_name}}.d --depfile-filter {{target_gen_dir}}/{{module_name}}.swiftmodule --bridge-header {{bridge_header}} $_extra_flag {{defines}} {{swiftflags}} {{include_dirs}} {{module_dirs}} {{inputs}}"
    }
  }
}

ios_toolchain("clang_x86") {
  toolchain_args = {
    current_cpu = "x86"
    current_os = "ios"
  }
}

ios_toolchain("clang_x64") {
  toolchain_args = {
    current_cpu = "x64"
    current_os = "ios"
  }
}

ios_toolchain("clang_arm") {
  toolchain_args = {
    current_cpu = "arm"
    current_os = "ios"
  }
}

ios_toolchain("clang_arm64") {
  toolchain_args = {
    current_cpu = "arm64"
    current_os = "ios"
  }
}
