Perfetto: first commit. Introduce build files

This CL sets up the directory structure, build files and
README for Perfetto. The build files are complete enough
to build a hello-world unittest, gtest, gmock and protobuf
from Linux and Mac OSX without depending on any external
tool. This will allow to build the project without a full
Android checkouot and hence being able to get test coverage
on other waterfalls (Chrome, Travis CI) and with a larger
set of compiler toolchains.
The plan is to generate Android.bp build files in the
next CLs to build the same targets also from the Android tree.

Change-Id: I7a15dcfdb24d5f857fc8c3a70757745741b92545
diff --git a/build/BUILD.gn b/build/BUILD.gn
new file mode 100644
index 0000000..8b3470f
--- /dev/null
+++ b/build/BUILD.gn
@@ -0,0 +1,155 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/android.gni")
+
+config("extra_warnings") {
+  cflags = [ "-Wextra" ]
+  if (is_clang) {
+    cflags += [
+      "-Weverything",
+      "-Wno-c++98-compat-pedantic",
+      "-Wno-c++98-compat",
+      "-Wno-gnu-include-next",
+      "-Wno-gnu-statement-expression",
+      "-Wno-padded",
+      "-Wno-reserved-id-macro",
+      "-Wno-unused-parameter",
+    ]
+  }
+}
+
+config("default") {
+  asmflags = []
+  cflags = []
+  cflags_c = []
+  cflags_cc = []
+  defines = []
+  ldflags = []
+  libs = []
+
+  include_dirs = [ ".." ]
+
+  cflags_cc += [ "-std=c++11" ]
+
+  cflags += [
+    "-fno-exceptions",
+    "-fno-rtti",
+    "-fstrict-aliasing",
+    "-fstack-protector",
+    "-fPIC",
+    "-Wa,--noexecstack",
+    "-Wformat",
+    "-Wall",
+    "-Werror",
+  ]
+
+  if (current_cpu == "arm") {
+    cflags += [
+      "-march=armv7-a",
+      "-mfpu=neon",
+      "-mthumb",
+    ]
+  } else if (current_cpu == "x86") {
+    asmflags += [ "-m32" ]
+    cflags += [
+      "-m32",
+      "-msse2",
+      "-mfpmath=sse",
+    ]
+    ldflags += [ "-m32" ]
+  }
+
+  if (is_linux) {
+    libs += [ "pthread" ]
+  }
+
+  if (is_android) {
+    asmflags += [ "--target=$android_abi_target" ]
+    cflags += [
+      "-isystem$android_ndk_root/$android_sysroot_subdir/usr/include",
+      "--sysroot=$android_ndk_root/$android_sysroot_subdir",
+      "-DANDROID",
+      "--target=$android_abi_target",
+    ]
+    cflags_cc += [
+      "-I$android_ndk_root/sources/cxx-stl/llvm-libc++/include",
+      "-I$android_ndk_root/sources/android/support/include",
+      "-I$android_ndk_root/sources/cxx-stl/llvm-libc++abi/include",
+    ]
+    ldflags += [
+      "-Wl,-z,nocopyreloc",
+      "-gcc-toolchain",
+      "$android_toolchain_root",
+      "--sysroot=$android_ndk_root/$android_sysroot_subdir",
+      "--target=$android_abi_target",
+      "-Wl,--exclude-libs,libunwind.a",
+      "-Wl,--exclude-libs,libgcc.a",
+      "-Wl,--exclude-libs,libc++_static.a",
+      "-Wl,--build-id",
+      "-Wl,--no-undefined",
+      "-Wl,-z,noexecstack",
+      "-Wl,-z,relro",
+      "-Wl,-z,now",
+      "-Wl,--warn-shared-textrel",
+      "-Wl,--fatal-warnings",
+    ]
+    lib_dirs = [
+      "$android_ndk_root/sources/cxx-stl/llvm-libc++/libs/$android_app_abi",
+      "$android_ndk_root/$android_sysroot_subdir/usr/lib",
+    ]
+    libs += [
+      "gcc",
+      "c++_static",
+      "c++abi",
+      "android_support",
+    ]
+  }
+}
+
+config("debug_symbols") {
+  if (is_android) {
+    cflags = [
+      "-gline-tables-only",
+      "-funwind-tables",
+    ]
+  } else {
+    cflags = [ "-g" ]
+  }
+}
+
+config("release") {
+  cflags = [
+    "-O3",
+    "-fdata-sections",
+    "-ffunction-sections",
+  ]
+  if (is_mac) {
+    ldflags = [ "-dead_strip" ]
+  } else {
+    ldflags = [ "-Wl,--gc-sections" ]
+  }
+  defines = [ "NDEBUG" ]
+}
+
+config("executable") {
+  if (is_android || is_linux) {
+    asmflags = [ "-fPIE" ]
+    cflags = [ "-fPIE" ]
+    ldflags = [
+      "-fPIE",
+      "-pie",
+    ]
+  }
+}
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
new file mode 100644
index 0000000..9333196
--- /dev/null
+++ b/build/BUILDCONFIG.gn
@@ -0,0 +1,74 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+  is_debug = true
+  is_clang = true
+
+  ar = "ar"
+  cc = "gcc"
+  cxx = "g++"
+}
+
+# Platform detection
+if (target_os == "") {
+  target_os = host_os
+}
+if (current_os == "") {
+  current_os = target_os
+}
+
+is_android = current_os == "android"
+is_linux = current_os == "linux"
+is_mac = current_os == "mac"
+
+if (target_cpu == "") {
+  target_cpu = host_cpu
+  if (is_android) {
+    target_cpu = "arm"
+  }
+}
+if (current_cpu == "") {
+  current_cpu = target_cpu
+}
+
+default_configs = [
+  "//build:default",
+  "//build:debug_symbols",
+  "//build:extra_warnings",
+]
+
+if (!is_debug) {
+  default_configs += [ "//build:release" ]
+}
+
+set_defaults("source_set") {
+  configs = default_configs
+}
+
+set_defaults("static_library") {
+  configs = default_configs
+}
+
+set_defaults("shared_library") {
+  configs = default_configs
+}
+
+set_defaults("executable") {
+  configs = default_configs
+  configs += [ "//build:executable" ]
+}
+
+set_default_toolchain("//build/toolchain:gcc_like")
+host_toolchain = "//build/toolchain:gcc_like_host"
diff --git a/build/android.gni b/build/android.gni
new file mode 100644
index 0000000..56c3255
--- /dev/null
+++ b/build/android.gni
@@ -0,0 +1,65 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+  android_api_level = 21
+  android_ndk_root = rebase_path("//buildtools/ndk")
+  _android_toolchain_version = "4.9"
+
+  if (host_os == "linux") {
+    android_host = "linux-x86_64"
+  } else if (host_os == "mac") {
+    android_host = "darwin-x86_64"
+  } else {
+    assert(false, "Need Android toolchain support for your build OS.")
+  }
+}
+
+declare_args() {
+  if (current_cpu == "x86") {
+    android_abi_target = "i686-linux-androideabi"
+    android_sysroot_subdir = "platforms/android-${android_api_level}/arch-x86"
+    android_prebuilt_arch = "android-x86"
+    android_toolchain_root = "$android_ndk_root/toolchains/x86-${_android_toolchain_version}/prebuilt/$android_host"
+  } else if (current_cpu == "arm") {
+    android_abi_target = "arm-linux-androideabi"
+    android_sysroot_subdir = "platforms/android-${android_api_level}/arch-arm"
+    android_prebuilt_arch = "android-arm"
+    android_toolchain_root = "$android_ndk_root/toolchains/arm-linux-androideabi-${_android_toolchain_version}/prebuilt/$android_host"
+  } else if (current_cpu == "x64") {
+    android_abi_target = "x86_64-linux-androideabi"
+    android_sysroot_subdir = "platforms/android-${android_api_level}/arch-x86_64"
+    android_prebuilt_arch = "android-x86_64"
+    android_toolchain_root = "$android_ndk_root/toolchains/x86_64-${_android_toolchain_version}/prebuilt/$android_host"
+  } else if (current_cpu == "arm64") {
+    android_abi_target = "aarch64-linux-android"
+    android_sysroot_subdir = "platforms/android-${android_api_level}/arch-arm64"
+    android_prebuilt_arch = "android-arm64"
+    android_toolchain_root = "$android_ndk_root/toolchains/aarch64-linux-android-${_android_toolchain_version}/prebuilt/$android_host"
+  } else {
+    assert(false, "Need android libgcc support for this arch.")
+  }
+
+  if (current_cpu == "x86") {
+    android_app_abi = "x86"
+  } else if (current_cpu == "arm") {
+    android_app_abi = "armeabi-v7a"
+  } else if (current_cpu == "x64") {
+    android_app_abi = "x86_64"
+  } else if (current_cpu == "arm64") {
+    android_app_abi = "arm64-v8a"
+  } else {
+    assert(false, "Unknown ABI: " + current_cpu)
+  }
+}
diff --git a/build/gn b/build/gn
new file mode 100755
index 0000000..fc0f354
--- /dev/null
+++ b/build/gn
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CMD="gn"
+source "$(dirname "${BASH_SOURCE[0]}")/run-buildtools-binary.sh"
diff --git a/build/install-build-deps b/build/install-build-deps
new file mode 100755
index 0000000..3a507d8
--- /dev/null
+++ b/build/install-build-deps
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import hashlib
+import logging
+import os
+import shutil
+import sys
+import urllib
+import zipfile
+
+PREBUILTS = (
+  # GN
+  ('buildtools/mac/gn',
+   'https://storage.googleapis.com/chromium-gn/c2c934d4dda1f470a6511b1015dda9a9fb1ce50b',
+   'c2c934d4dda1f470a6511b1015dda9a9fb1ce50b',
+   'darwin'
+  ),
+  ('buildtools/linux64/gn',
+   'https://storage.googleapis.com/chromium-gn/b53fa13e950948c6f9a062189b76b34a9610281f',
+   'b53fa13e950948c6f9a062189b76b34a9610281f',
+   'linux2'
+  ),
+
+  # Ninja
+  ('buildtools/mac/ninja',
+   'https://storage.googleapis.com/fuchsia-build/fuchsia/ninja/mac/a1db595e824c50cf565fbf0af2437fd91b7babf4',
+   'a1db595e824c50cf565fbf0af2437fd91b7babf4',
+   'darwin'
+  ),
+  ('buildtools/linux64/ninja',
+   'https://storage.googleapis.com/fuchsia-build/fuchsia/ninja/linux64/d35b36c84a09f7e38b25947cafada10e8bf835bc',
+   'd35b36c84a09f7e38b25947cafada10e8bf835bc',
+   'linux2'
+  ),
+
+  # Android NDK
+  ('buildtools/ndk.zip',
+   'https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip',
+   'ea4b5d76475db84745aa8828000d009625fc1f98',
+   'darwin'
+  ),
+  ('buildtools/ndk.zip',
+   'https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip',
+   '0bf02d4e8b85fd770fd7b9b2cdec57f9441f27a2',
+   'linux2'
+  ),
+
+  # Keep in sync with Android's //external/googletest/README.version .
+  ('buildtools/googletest.zip',
+   'https://github.com/google/googletest/archive/ff07a5de0e81580547f1685e101194ed1a4fcd56.zip',
+   'c7edec7d7e6db1fc37a20710de9c4d89e3a3893b',
+   'all'
+  ),
+
+  # Keep in sync with Android's //external/protobuf/README.version .
+  ('buildtools/protobuf.zip',
+   'https://github.com/google/protobuf/releases/download/v3.0.0-beta-3/protobuf-cpp-3.0.0-beta-3.zip',
+   '3caec60aa9d8eefc8c3c3201b6b8ca19935edb89',
+   'all'
+  ),
+)
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+def ReadFile(path):
+  if not os.path.exists(path):
+    return None
+  with open(path) as f:
+      return f.read().strip()
+
+
+def MkdirRecursive(rel_path):
+  cwd = ROOT_DIR
+  for part in rel_path.split('/'):
+    cwd = os.path.join(cwd, part)
+    if not os.path.exists(cwd):
+      os.makedirs(cwd)
+    else:
+      assert(os.path.isdir(cwd))
+
+
+def HashLocalFile(path):
+  if not os.path.exists(path):
+    return None
+  with open(path, 'rb') as f:
+    return hashlib.sha1(f.read()).hexdigest()
+
+
+def ExtractZipfilePreservePermissions(zf, info, path):
+  zf.extract(info.filename, path=path)
+  target_path = os.path.join(path, info.filename)
+  min_acls = 0o755 if info.filename.endswith('/') else 0o644
+  os.chmod(target_path, (info.external_attr >> 16L) | min_acls)
+
+
+def Main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--skip', action='append', default=[])
+  args = parser.parse_args()
+  skip_set = set(args.skip)
+  for rel_path, url, expected_sha1, platform in PREBUILTS:
+    if platform != 'all' and platform != sys.platform:
+      continue
+    if os.path.basename(rel_path) in skip_set:
+      logging.info('Skipping %s because of --skip cmdline arg', rel_path)
+      continue
+    local_path = os.path.join(ROOT_DIR, rel_path)
+    is_zip = local_path.lower().endswith('.zip')
+    zip_target_dir = local_path[:-4] if is_zip else None
+    zip_dir_stamp = os.path.join(zip_target_dir, '.stamp') if is_zip else None
+
+    if ((not is_zip and HashLocalFile(local_path) == expected_sha1) or
+        (is_zip and ReadFile(zip_dir_stamp) == expected_sha1)):
+      continue
+    MkdirRecursive(os.path.dirname(rel_path))
+    if HashLocalFile(local_path) != expected_sha1:
+      download_path = local_path + '.tmp'
+      logging.info('Downloading %s from %s', local_path, url)
+      urllib.urlretrieve(url, download_path)
+      os.chmod(download_path, 0o755)
+      if (HashLocalFile(download_path) != expected_sha1):
+        os.remove(download_path)
+        logging.fatal('SHA1 mismatch for %s', download_path)
+        return 1
+      os.rename(download_path, local_path)
+    assert(HashLocalFile(local_path) == expected_sha1)
+
+    if is_zip:
+      logging.info('Extracting %s into %s' % (local_path, zip_target_dir))
+      assert(os.path.commonprefix((ROOT_DIR, zip_target_dir)) == ROOT_DIR)
+      if os.path.exists(zip_target_dir):
+        logging.info('Deleting stale dir %s' % zip_target_dir)
+        shutil.rmtree(zip_target_dir)
+      with zipfile.ZipFile(local_path, 'r') as zf:
+        for info in zf.infolist():
+          ExtractZipfilePreservePermissions(zf, info, zip_target_dir)
+
+        # If the zip contains one root folder, rebase one level up moving all
+        # its sub files and folders inside |target_dir|.
+        subdir = os.listdir(zip_target_dir)
+        if len(subdir) == 1:
+          subdir = os.path.join(zip_target_dir, subdir[0])
+          if os.path.isdir(subdir):
+            for subf in os.listdir(subdir):
+              shutil.move(os.path.join(subdir,subf), zip_target_dir)
+            os.rmdir(subdir)
+        with open(zip_dir_stamp, 'w') as stamp_file:
+          stamp_file.write(expected_sha1)
+        os.remove(local_path)
+
+
+if __name__ == '__main__':
+  logging.basicConfig(level=logging.INFO)
+  sys.exit(Main())
diff --git a/build/ninja b/build/ninja
new file mode 100755
index 0000000..724ccb0
--- /dev/null
+++ b/build/ninja
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CMD="ninja"
+source "$(dirname "${BASH_SOURCE[0]}")/run-buildtools-binary.sh"
diff --git a/build/run-buildtools-binary.sh b/build/run-buildtools-binary.sh
new file mode 100644
index 0000000..4634994
--- /dev/null
+++ b/build/run-buildtools-binary.sh
@@ -0,0 +1,41 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+if [[ -n "$BASH_VERSION" && "${BASH_SOURCE:-$0}" == "$0" ]]; then
+  echo "ERROR: ${BASH_SOURCE:-$0} must be sourced"
+  exit 1
+fi
+
+readonly PROJECT_ROOT="$(cd -P ${BASH_SOURCE[0]%/*}/..; pwd)"
+
+case "$(uname -s | tr [:upper:] [:lower:])" in
+  darwin)
+    readonly OS="mac";;
+  linux)
+    readonly OS="linux64";;
+  *)
+    echo "Unsupported platform"
+    exit 1
+    ;;
+esac
+
+BIN_PATH="$PROJECT_ROOT/buildtools/$OS/$CMD"
+if [ ! -x "$BIN_PATH" ]; then
+  echo "Cannot find $BIN_PATH. Run build/install-build-deps first."
+  exit 1
+fi
+
+exec "$BIN_PATH" "$@"
diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn
new file mode 100644
index 0000000..d6dc1cb
--- /dev/null
+++ b/build/toolchain/BUILD.gn
@@ -0,0 +1,140 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/android.gni")
+
+declare_args() {
+  host_ar = ar
+  host_cc = cc
+  host_cxx = cxx
+
+  if (is_android) {
+    target_ar = "$android_toolchain_root/bin/ar"
+    target_cc =
+        "$android_ndk_root/toolchains/llvm/prebuilt/$android_host/bin/clang"
+    target_cxx =
+        "$android_ndk_root/toolchains/llvm/prebuilt/$android_host/bin/clang++"
+  } else {
+    target_ar = ar
+    target_cc = cc
+    target_cxx = cxx
+  }
+  cc_wrapper = ""
+}
+
+python = "python"
+stamp = "touch"
+
+template("gcc_like_toolchain") {
+  toolchain(target_name) {
+    ar = invoker.ar
+    cc = invoker.cc
+    cxx = invoker.cxx
+    lib_switch = "-l"
+    lib_dir_switch = "-L"
+
+    tool("cc") {
+      depfile = "{{output}}.d"
+      command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+      depsformat = "gcc"
+      outputs = [
+        "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+      ]
+      description = "compile {{source}}"
+    }
+
+    tool("cxx") {
+      depfile = "{{output}}.d"
+      command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
+      depsformat = "gcc"
+      outputs = [
+        "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+      ]
+      description = "compile {{source}}"
+    }
+
+    tool("asm") {
+      depfile = "{{output}}.d"
+      command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
+      depsformat = "gcc"
+      outputs = [
+        "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+      ]
+      description = "assemble {{source}}"
+    }
+
+    tool("alink") {
+      rspfile = "{{output}}.rsp"
+      rspfile_content = "{{inputs}}"
+      command = "$ar {{output}} $rspfile"
+      outputs = [
+        "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
+      ]
+      default_output_extension = ".a"
+      output_prefix = "lib"
+      description = "link {{output}}"
+    }
+
+    tool("solink") {
+      soname = "{{target_output_name}}{{output_extension}}"
+
+      rpath = "-Wl,-soname,$soname"
+      if (is_mac) {
+        rpath = "-Wl,-install_name,@rpath/$soname"
+      }
+
+      command = "$cc_wrapper $cxx -shared {{ldflags}} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
+      outputs = [
+        "{{root_out_dir}}/$soname",
+      ]
+      output_prefix = "lib"
+      default_output_extension = ".so"
+      description = "link {{output}}"
+    }
+
+    tool("link") {
+      command = "$cc_wrapper $cxx {{ldflags}} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
+      outputs = [
+        "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
+      ]
+      description = "link {{output}}"
+    }
+
+    tool("stamp") {
+      command = "$stamp {{output}}"
+      description = "stamp {{output}}"
+    }
+
+    toolchain_args = {
+      current_cpu = invoker.cpu
+      current_os = invoker.os
+    }
+  }
+}
+
+gcc_like_toolchain("gcc_like") {
+  cpu = current_cpu
+  os = current_os
+  ar = target_ar
+  cc = target_cc
+  cxx = target_cxx
+}
+
+gcc_like_toolchain("gcc_like_host") {
+  cpu = host_cpu
+  os = host_os
+  ar = host_ar
+  cc = host_cc
+  cxx = host_cxx
+}