Add expectation files for chrome's cc and ld flags
This will make sure we are notified of chrome native build flags changes
to match with out of repo compilations of native code.
Change-Id: Id647e3500935c07352f54ba19df48768c70f0374
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2756707
Commit-Queue: Mohamed Heikal <[email protected]>
Reviewed-by: Andrew Grieve <[email protected]>
Cr-Commit-Position: refs/heads/master@{#862817}
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 78093f1..d8ce922 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1303,6 +1303,7 @@
'build/android/gyp/assert_static_initializers.pydeps',
'build/android/gyp/bytecode_processor.pydeps',
'build/android/gyp/bytecode_rewriter.pydeps',
+ 'build/android/gyp/check_flag_expectations.pydeps',
'build/android/gyp/compile_java.pydeps',
'build/android/gyp/compile_resources.pydeps',
'build/android/gyp/copy_ex.pydeps',
diff --git a/build/android/gyp/check_flag_expectations.py b/build/android/gyp/check_flag_expectations.py
new file mode 100644
index 0000000..a6e47db
--- /dev/null
+++ b/build/android/gyp/check_flag_expectations.py
@@ -0,0 +1,131 @@
+# Copyright 2021 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 argparse
+
+from util import build_utils
+from util import diff_utils
+
+IGNORE_FLAG_PREFIXES = [
+ # For cflags.
+ '-DANDROID_NDK_VERSION_ROLL',
+ '-DCR_LIBCXX_REVISION',
+ '-I',
+ '-g',
+ '-fcrash-diagnostics-dir=',
+ '-fprofile',
+ '--no-system-header-prefix',
+ '--system-header-prefix',
+ '-isystem',
+ '-iquote',
+ '-fmodule-map',
+ '-frandom-seed',
+ '-c ',
+ '-o ',
+ '-fmodule-name=',
+ '--sysroot=',
+ '-fcolor-diagnostics',
+ '-MF ',
+ '-MD',
+
+ # For ldflags.
+ '-Wl,--thinlto-cache-dir',
+ '-Wl,--thinlto-cache-policy',
+ '-Wl,--thinlto-jobs',
+ '-Wl,--start-lib',
+ '-Wl,--end-lib',
+ '-Wl,-whole-archive',
+ '-Wl,-no-whole-archive',
+ '-l',
+ '-L',
+ '-Wl,-soname',
+ '-Wl,-version-script',
+ '-Wl,--version-script',
+ '-fdiagnostics-color',
+ '-Wl,--color-diagnostics',
+ '-B',
+ '-Wl,--dynamic-linker',
+ '-DCR_CLANG_REVISION=',
+]
+
+FLAGS_WITH_PARAMS = (
+ '-Xclang',
+ '-mllvm',
+ '-Xclang -fdebug-compilation-dir',
+ '-Xclang -add-plugin',
+)
+
+
+def KeepFlag(flag):
+ return not any(flag.startswith(prefix) for prefix in IGNORE_FLAG_PREFIXES)
+
+
+def MergeFlags(flags):
+ flags = _MergeFlagsHelper(flags)
+ # For double params eg: -Xclang -fdebug-compilation-dir
+ flags = _MergeFlagsHelper(flags)
+ return flags
+
+
+def _MergeFlagsHelper(flags):
+ merged_flags = []
+ while flags:
+ current_flag = flags.pop(0)
+ if flags:
+ next_flag = flags[0]
+ else:
+ next_flag = None
+ merge_flags = False
+
+ # Special case some flags that always come with params.
+ if current_flag in FLAGS_WITH_PARAMS:
+ merge_flags = True
+ # Assume flags without '-' are a param.
+ if next_flag and not next_flag.startswith('-'):
+ merge_flags = True
+ # Special case -plugin-arg prefix because it has the plugin name.
+ if current_flag.startswith('-Xclang -plugin-arg'):
+ merge_flags = True
+ if merge_flags:
+ merged_flag = '{} {}'.format(current_flag, next_flag)
+ merged_flags.append(merged_flag)
+ flags.pop(0)
+ else:
+ merged_flags.append(current_flag)
+ return merged_flags
+
+
+def ParseFlags(flag_file_path):
+ flags = []
+ with open(flag_file_path) as f:
+ for flag in f.read().splitlines():
+ if KeepFlag(flag):
+ flags.append(flag)
+ return flags
+
+
+def main():
+ """Compare the flags with the checked in list."""
+ parser = argparse.ArgumentParser()
+ diff_utils.AddCommandLineFlags(parser)
+ parser.add_argument('--current-flags',
+ help='Path to flags to check against expectations.')
+ options = parser.parse_args()
+
+ flags = ParseFlags(options.current_flags)
+ flags = MergeFlags(flags)
+
+ msg = """
+This expectation file is meant to inform the build team about changes to
+flags used when building native libraries in chrome (most importantly any
+that relate to security). This is to ensure the flags are replicated when
+building native libraries outside of the repo. Please update the .expected
+files and a WATCHLIST entry will alert the build team to your change."""
+ diff_utils.CheckExpectations('\n'.join(sorted(flags)),
+ options,
+ custom_msg=msg)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/build/android/gyp/check_flag_expectations.pydeps b/build/android/gyp/check_flag_expectations.pydeps
new file mode 100644
index 0000000..d8c394a
--- /dev/null
+++ b/build/android/gyp/check_flag_expectations.pydeps
@@ -0,0 +1,7 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/check_flag_expectations.pydeps build/android/gyp/check_flag_expectations.py
+../../gn_helpers.py
+check_flag_expectations.py
+util/__init__.py
+util/build_utils.py
+util/diff_utils.py
diff --git a/build/android/gyp/util/diff_utils.py b/build/android/gyp/util/diff_utils.py
index 726aa85..a109100 100755
--- a/build/android/gyp/util/diff_utils.py
+++ b/build/android/gyp/util/diff_utils.py
@@ -88,9 +88,10 @@
help='Verify the expectation and exit.')
-def CheckExpectations(actual_data, options):
- with build_utils.AtomicOutput(options.actual_file) as f:
- f.write(actual_data.encode('utf8'))
+def CheckExpectations(actual_data, options, custom_msg=''):
+ if options.actual_file:
+ with build_utils.AtomicOutput(options.actual_file) as f:
+ f.write(actual_data.encode('utf8'))
if options.expected_file_base:
actual_data = _GenerateDiffWithOnlyAdditons(options.expected_file_base,
actual_data)
@@ -106,13 +107,15 @@
LogDog tip: Use "Raw log" or "Switch to lite mode" before copying:
https://bugs.chromium.org/p/chromium/issues/detail?id=984616
+{}
+
To update expectations, run:
########### START ###########
patch -p1 <<'END_DIFF'
{}
END_DIFF
############ END ############
-""".format(diff_text)
+""".format(custom_msg, diff_text)
sys.stderr.write(fail_msg)
diff --git a/build/android/native_flags/BUILD.gn b/build/android/native_flags/BUILD.gn
new file mode 100644
index 0000000..9c5be70
--- /dev/null
+++ b/build/android/native_flags/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2021 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.
+
+if (current_toolchain == default_toolchain) {
+ import("//build/toolchain/toolchain.gni")
+
+ # A toolchain that will capture compiler and linker arguments to a file.
+ toolchain("flagcapture") {
+ tool("cxx") {
+ cxx = rebase_path("argcapture.py", root_build_dir)
+ command = "$cxx {{output}} {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
+ outputs = [ "{{root_out_dir}}/{{label_name}}.txt" ]
+ }
+ tool("solink") {
+ solink = rebase_path("argcapture.py", root_build_dir)
+ command = "$solink {{output}} {{ldflags}}"
+ outputs = [ "{{root_out_dir}}/{{label_name}}.txt" ]
+ }
+ tool("alink") {
+ command = "this-should-never-run"
+ outputs = [ "this-will-never-exist" ]
+ }
+ tool("stamp") {
+ command = stamp_command
+ description = stamp_description
+ }
+ }
+} else if (current_toolchain == "//build/android/native_flags:flagcapture") {
+ # This will record flags from all default configs of the default toolchain.
+ source_set("default_ccflags") {
+ sources = [ "empty.cc" ]
+ }
+ shared_library("default_ldflags") {
+ no_default_deps = true
+ }
+}
diff --git a/build/android/native_flags/argcapture.py b/build/android/native_flags/argcapture.py
new file mode 100755
index 0000000..159b03ab
--- /dev/null
+++ b/build/android/native_flags/argcapture.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright 2021 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.
+"""Writes arguments to a file."""
+
+import sys
+
+
+def main():
+ with open(sys.argv[1], 'w') as f:
+ f.write('\n'.join(sys.argv[2:]))
+ f.write('\n')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/build/android/native_flags/empty.cc b/build/android/native_flags/empty.cc
new file mode 100644
index 0000000..94aac14
--- /dev/null
+++ b/build/android/native_flags/empty.cc
@@ -0,0 +1,5 @@
+// Copyright 2021 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.
+
+// This file just needs to exist to appease GN.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index a64cefa..6c513ce 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1,5 +1,5 @@
-# Use of this source code is governed by a BSD-style license that can be
# 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("//build/android/resource_sizes.gni")
@@ -98,6 +98,8 @@
!is_java_debug && !enable_chrome_android_internal &&
android_channel == "stable"
+_enable_flags_verification = target_cpu == "arm" && is_official_build
+
jinja_template("chrome_public_android_manifest") {
input = "java/AndroidManifest.xml"
output = chrome_public_android_manifest
@@ -3544,7 +3546,8 @@
}
# Used by android-binary-size trybot to validate expectations.
-if (_enable_libs_and_assets_verification || _enable_manifest_verification) {
+if (_enable_libs_and_assets_verification || _enable_manifest_verification ||
+ _enable_flags_verification) {
group("validate_expectations") {
deps = []
if (_enable_libs_and_assets_verification) {
@@ -3565,5 +3568,8 @@
"//android_webview:trichrome_webview_base_bundle_module_validate_android_manifest",
]
}
+ if (_enable_flags_verification) {
+ deps += [ "//chrome/android/expectations:native_flags_expectations" ]
+ }
}
}
diff --git a/chrome/android/expectations/BUILD.gn b/chrome/android/expectations/BUILD.gn
new file mode 100644
index 0000000..d0512f5
--- /dev/null
+++ b/chrome/android/expectations/BUILD.gn
@@ -0,0 +1,66 @@
+# Use of this source code is governed by a BSD-style license that can be
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/python.gni")
+
+_flagcapture_out_dir =
+ get_label_info("foo(//build/android/native_flags:flagcapture)",
+ "root_out_dir")
+action_with_pydeps("native_cc_flags_expectations") {
+ script = "//build/android/gyp/check_flag_expectations.py"
+ _actual_flags = "$_flagcapture_out_dir/default_ccflags.txt"
+ _expected_flags = "//chrome/android/expectations/ccflags.expected"
+ _failure_file =
+ "$expectations_failure_dir/native_cc_flags_expectations.failed"
+ inputs = [
+ _actual_flags,
+ _expected_flags,
+ ]
+ outputs = [ _failure_file ]
+ args = [
+ "--current-flags",
+ rebase_path(_actual_flags, root_build_dir),
+ "--expected-file",
+ rebase_path(_expected_flags, root_build_dir),
+ "--failure-file",
+ rebase_path(_failure_file, root_build_dir),
+ ]
+ if (fail_on_android_expectations) {
+ args += [ "--fail-on-expectations" ]
+ }
+ deps = [ "//build/android/native_flags:default_ccflags(//build/android/native_flags:flagcapture)" ]
+}
+
+action_with_pydeps("native_ld_flags_expectations") {
+ script = "//build/android/gyp/check_flag_expectations.py"
+ _actual_flags = "$_flagcapture_out_dir/default_ldflags.txt"
+ _expected_flags = "//chrome/android/expectations/ldflags.expected"
+ _failure_file =
+ "$expectations_failure_dir/native_ld_flags_expectations.failed"
+ inputs = [
+ _actual_flags,
+ _expected_flags,
+ ]
+ outputs = [ _failure_file ]
+ args = [
+ "--current-flags",
+ rebase_path(_actual_flags, root_build_dir),
+ "--expected-file",
+ rebase_path(_expected_flags, root_build_dir),
+ "--failure-file",
+ rebase_path(_failure_file, root_build_dir),
+ ]
+ if (fail_on_android_expectations) {
+ args += [ "--fail-on-expectations" ]
+ }
+ deps = [ "//build/android/native_flags:default_ldflags(//build/android/native_flags:flagcapture)" ]
+}
+
+group("native_flags_expectations") {
+ deps = [
+ ":native_cc_flags_expectations",
+ ":native_ld_flags_expectations",
+ ]
+}
diff --git a/chrome/android/expectations/README.md b/chrome/android/expectations/README.md
index 35c8e65..5de4f15 100644
--- a/chrome/android/expectations/README.md
+++ b/chrome/android/expectations/README.md
@@ -27,7 +27,7 @@
Some configs are explicitly added ([ex](proguard.flags)) while others are pulled
in implicitly by GN deps (ex. `aar_prebuilt()` deps, or any target that specifies
-`proguard_configs = [...]`).
+`proguard_configs = [...]`).
Since proguard configs are global in nature, it is important that all configs go
through code review. We use these `.expected` files to ensure that they do.
@@ -79,6 +79,20 @@
When we change build gn files, the native libraries and assets can sometimes
be changed in an unexpected way.
+## Native Flags
+The compile and link flags that are used to build chrome.
+
+### What are `*flags.expected` files?
+`*flags.expected` files store in a text format the list of flags passed to
+the compiler and linker when building chrome's native libraries.
+
+### Why do we care about compile/link flag discrepancies?
+Some of chrome's native code is compiled outside of the repo. The
+`*flags.expected` files inform the build team that these flags changed (most
+importantly if any relate to security). When you update a `*flags.expected`
+file the build team is informed (via a WATCHLIST entry) and can then choose
+to add these flags for out-of-repo native library builds.
+
## Build failures caused by `*.expected` files
### What is the build error telling me?
diff --git a/chrome/android/expectations/ccflags.expected b/chrome/android/expectations/ccflags.expected
new file mode 100644
index 0000000..eca43af
--- /dev/null
+++ b/chrome/android/expectations/ccflags.expected
@@ -0,0 +1,79 @@
+--param=ssp-buffer-size=4
+--target=arm-linux-androideabi21
+-DANDROID
+-DDYNAMIC_ANNOTATIONS_ENABLED=0
+-DHAVE_SYS_UIO_H
+-DNDEBUG
+-DNO_UNWIND_TABLES
+-DNVALGRIND
+-DOFFICIAL_BUILD
+-D_FORTIFY_SOURCE=2
+-D_GNU_SOURCE
+-D_LIBCPP_ABI_UNSTABLE
+-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
+-D_LIBCPP_ENABLE_NODISCARD
+-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS
+-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS
+-D__STDC_CONSTANT_MACROS
+-D__STDC_FORMAT_MACROS
+-Oz
+-Wall
+-Werror
+-Wextra
+-Wextra-semi
+-Wheader-hygiene
+-Wimplicit-fallthrough
+-Wno-builtin-assume-aligned-alignment
+-Wno-c++11-narrowing
+-Wno-deprecated-copy
+-Wno-final-dtor-non-final-class
+-Wno-ignored-pragma-optimize
+-Wno-implicit-int-float-conversion
+-Wno-max-tokens
+-Wno-missing-field-initializers
+-Wno-non-c-typedef-for-linkage
+-Wno-psabi
+-Wno-trigraphs
+-Wno-undefined-var-template
+-Wno-unneeded-internal-declaration
+-Wno-unused-parameter
+-Wstring-conversion
+-Wtautological-overlap-compare
+-Wthread-safety
+-Wunreachable-code
+-Xclang -add-plugin -Xclang find-bad-constructs
+-Xclang -fdebug-compilation-dir -Xclang .
+-Xclang -fno-experimental-new-pass-manager
+-Xclang -plugin-arg-find-bad-constructs -Xclang check-ipc
+-Xclang -plugin-arg-find-bad-constructs -Xclang checked-ptr-as-trivial-member
+-fPIC
+-fcomplete-member-pointers
+-fdata-sections
+-fdebug-info-for-profiling
+-ffunction-sections
+-ffunction-sections
+-flto=thin
+-fmerge-all-constants
+-fno-asynchronous-unwind-tables
+-fno-delete-null-pointer-checks
+-fno-exceptions
+-fno-ident
+-fno-rtti
+-fno-short-enums
+-fno-strict-aliasing
+-fno-trigraphs
+-fno-unwind-tables
+-fomit-frame-pointer
+-fsplit-lto-unit
+-fstack-protector
+-fvisibility-inlines-hidden
+-fvisibility=hidden
+-march=armv7-a
+-mfloat-abi=softfp
+-mfpu=neon
+-mllvm -instcombine-lower-dbg-declare=0
+-mthumb
+-mtune=generic-armv7-a
+-no-canonical-prefixes
+-nostdinc++
+-std=c++14
diff --git a/chrome/android/expectations/ldflags.expected b/chrome/android/expectations/ldflags.expected
new file mode 100644
index 0000000..ceb45f7
--- /dev/null
+++ b/chrome/android/expectations/ldflags.expected
@@ -0,0 +1,26 @@
+--target=arm-linux-androideabi21
+-Werror
+-Wl,--as-needed
+-Wl,--build-id=sha1
+-Wl,--exclude-libs=libgcc.a
+-Wl,--exclude-libs=libvpx_assembly_arm.a
+-Wl,--fatal-warnings
+-Wl,--gc-sections
+-Wl,--icf=all
+-Wl,--lto-O0
+-Wl,--lto-legacy-pass-manager
+-Wl,--no-call-graph-profile-sort
+-Wl,--no-rosegment
+-Wl,--warn-shared-textrel
+-Wl,--warn-shared-textrel
+-Wl,-O2
+-Wl,-mllvm,-import-instr-limit=5
+-Wl,-z,defs
+-Wl,-z,noexecstack
+-Wl,-z,now
+-Wl,-z,relro
+-fPIC
+-flto=thin
+-fuse-ld=lld
+-march=armv7-a
+-nostdlib++