chromium/build/config/clang/BUILD.gn

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

import("//build/config/pch.gni")
import("//build/config/rust.gni")
import("clang.gni")

if (is_ios) {
  import("//build/config/ios/config.gni")  # For `target_environment`
}

config("raw_ptr_check") {
  if (clang_use_chrome_plugins || clang_use_raw_ptr_plugin) {
    cflags = []

    # The plugin is built directly into clang, so there's no need to load it
    # dynamically.
    cflags += [
      "-Xclang",
      "-add-plugin",
      "-Xclang",
      "raw-ptr-plugin",

      "-Xclang",
      "-plugin-arg-raw-ptr-plugin",
      "-Xclang",
      "check-raw-ptr-to-stack-allocated",

      "-Xclang",
      "-plugin-arg-raw-ptr-plugin",
      "-Xclang",
      "disable-check-raw-ptr-to-stack-allocated-error",

      # TODO(crbug.com/40944547): Remove when raw_ptr check has been
      # enabled for the dawn repo.
      "-Xclang",
      "-plugin-arg-raw-ptr-plugin",
      "-Xclang",
      "raw-ptr-exclude-path=" +
          rebase_path("//third_party/dawn/", root_build_dir),
    ]

    if (enable_check_raw_ptr_fields) {
      cflags += [
        "-Xclang",
        "-plugin-arg-raw-ptr-plugin",
        "-Xclang",
        "check-raw-ptr-fields",
      ]
    }

    if (enable_check_raw_ref_fields) {
      cflags += [
        "-Xclang",
        "-plugin-arg-raw-ptr-plugin",
        "-Xclang",
        "check-raw-ref-fields",
      ]
    }
  }
}

config("find_bad_constructs") {
  if (clang_use_chrome_plugins) {
    configs = []
    cflags = []

    # The plugin is built directly into clang, so there's no need to load it
    # dynamically.
    cflags += [
      "-Xclang",
      "-add-plugin",
      "-Xclang",
      "find-bad-constructs",

      "-Xclang",
      "-plugin-arg-find-bad-constructs",
      "-Xclang",
      "span-ctor-from-string-literal",

      "-Xclang",
      "-plugin-arg-find-bad-constructs",
      "-Xclang",
      "raw-ref-template-as-trivial-member",

      "-Xclang",
      "-plugin-arg-find-bad-constructs",
      "-Xclang",
      "check-stack-allocated",

      # TODO(danakj): Delete this after the next clang roll.
      "-Xclang",
      "-plugin-arg-find-bad-constructs",
      "-Xclang",
      "check-allow-auto-typedefs-better-nested",
    ]

    if (is_linux || is_chromeos || is_android || is_fuchsia) {
      cflags += [
        "-Xclang",
        "-plugin-arg-find-bad-constructs",
        "-Xclang",
        "check-ipc",
      ]
    }

    configs += [ ":raw_ptr_check" ]
  }
}

# A plugin for incrementally applying the -Wunsafe-buffer-usage warning.
#
# To use the plugin, the project must specify a path as
# `clang_unsafe_buffers_paths` in the `//.gn` file. This path points to a text
# file that controls where the warning is checked.
#
# See //build/config/unsafe_buffers_paths.txt for an example file, this it the
# file used by Chromium.
#
# This build configuration is not supported when `enable_precompiled_headers`
# is on because the pragmas that enable and disable unsafe-buffers warnings are
# not serialized to precompiled header files, and thus we get warnings that we
# should not.
config("unsafe_buffers") {
  if (clang_use_chrome_plugins && clang_unsafe_buffers_paths != "" &&
      !enable_precompiled_headers) {
    cflags = [
      "-DUNSAFE_BUFFERS_BUILD",

      "-Xclang",
      "-add-plugin",
      "-Xclang",
      "unsafe-buffers",

      "-Xclang",
      "-plugin-arg-unsafe-buffers",
      "-Xclang",
      rebase_path(clang_unsafe_buffers_paths, root_build_dir),
    ]
  }
}

# Enables some extra Clang-specific warnings. Some third-party code won't
# compile with these so may want to remove this config.
config("extra_warnings") {
  cflags = [
    "-Wheader-hygiene",

    # Warns when a const char[] is converted to bool.
    "-Wstring-conversion",

    "-Wtautological-overlap-compare",
  ]
}

group("llvm-symbolizer_data") {
  if (is_win) {
    data = [ "$clang_base_path/bin/llvm-symbolizer.exe" ]
  } else {
    data = [ "$clang_base_path/bin/llvm-symbolizer" ]
  }
}

template("clang_lib") {
  if (!defined(invoker.libname)) {
    not_needed(invoker, "*")
    config(target_name) {
    }
  } else {
    config(target_name) {
      _dir = ""
      _libname = invoker.libname
      _prefix = "lib"
      _suffix = ""
      _ext = "a"
      if (is_win) {
        _dir = "windows"
        _prefix = ""
        _ext = "lib"
        if (current_cpu == "x64") {
          _suffix = "-x86_64"
        } else if (current_cpu == "x86") {
          _suffix = "-i386"
        } else if (current_cpu == "arm64") {
          _suffix = "-aarch64"
        } else {
          assert(false)  # Unhandled cpu type
        }
      } else if (is_apple) {
        _dir = "darwin"
      } else if (is_linux || is_chromeos) {
        if (current_cpu == "x64") {
          _dir = "x86_64-unknown-linux-gnu"
        } else if (current_cpu == "x86") {
          _dir = "i386-unknown-linux-gnu"
        } else if (current_cpu == "arm") {
          _dir = "armv7-unknown-linux-gnueabihf"
        } else if (current_cpu == "arm64") {
          _dir = "aarch64-unknown-linux-gnu"
        } else {
          assert(false)  # Unhandled cpu type
        }
      } else if (is_fuchsia) {
        if (current_cpu == "x64") {
          _dir = "x86_64-unknown-fuchsia"
        } else if (current_cpu == "arm64") {
          _dir = "aarch64-unknown-fuchsia"
        } else {
          assert(false)  # Unhandled cpu type
        }
      } else if (is_android) {
        _dir = "linux"
        if (current_cpu == "x64") {
          _suffix = "-x86_64-android"
        } else if (current_cpu == "x86") {
          _suffix = "-i686-android"
        } else if (current_cpu == "arm") {
          _suffix = "-arm-android"
        } else if (current_cpu == "arm64") {
          _suffix = "-aarch64-android"
        } else if (current_cpu == "riscv64") {
          _suffix = "-riscv64-android"
        } else {
          assert(false)  # Unhandled cpu type
        }
      } else {
        assert(false)  # Unhandled target platform
      }

      _clang_lib_dir = "$clang_base_path/lib/clang/$clang_version/lib"
      _lib_file = "${_prefix}clang_rt.${_libname}${_suffix}.${_ext}"
      libs = [ "$_clang_lib_dir/$_dir/$_lib_file" ]
    }
  }
}

# Adds a dependency on the Clang runtime library clang_rt.builtins.
clang_lib("compiler_builtins") {
  if (is_mac) {
    libname = "osx"
  } else if (is_ios) {
    if (target_environment == "simulator") {
      libname = "iossim"
    } else if (target_environment == "catalyst") {
      libname = "osx"
    } else {
      libname = "ios"
    }
  } else {
    libname = "builtins"
  }
}

# Adds a dependency on the Clang runtime library clang_rt.profile.
clang_lib("compiler_profile") {
  if (!toolchain_has_rust) {
    # This is only used when `toolchain_has_rust` to support Rust linking.
    #
    # Don't define libname which makes this target do nothing.
  } else if (is_mac) {
    libname = "profile_osx"
  } else if (is_ios) {
    if (target_environment == "simulator") {
      libname = "profile_iossim"
    } else if (target_environment == "catalyst") {
      # We don't enable clang coverage on iOS device builds, and the library is
      # not part of the Clang package tarball as a result.
      #
      # Don't define libname which makes this target do nothing.
    } else {
      # We don't enable clang coverage on iOS device builds, and the library is
      # not part of the Clang package tarball as a result.
      #
      # Don't define libname which makes this target do nothing.
    }
  } else {
    libname = "profile"
  }
}