Merge flutter/engine into framework

Adds files from flutter/flaux which contain modifications for the engine
structure. The history for engine/ has been edited. Please see
flutter/engine for the original PRs.
This commit is contained in:
John McDole
2024-12-17 12:58:01 -08:00
5866 changed files with 1270180 additions and 1 deletions

13
.gitignore vendored
View File

@@ -1,6 +1,10 @@
# Do not remove or rename entries in this file, only add new ones
# See https://github.com/flutter/flutter/issues/128635 for more context.
# This is dynamic in a monorepo
bin/internal/engine.version
bin/internal/engine.realm
# Miscellaneous
*.class
*.lock
@@ -74,7 +78,6 @@ unlinked_spec.ds
**/android/**/GeneratedPluginRegistrant.java
**/android/key.properties
*.jks
**/.cxx/
# iOS/XCode related
**/ios/**/*.mode1v3
@@ -139,3 +142,11 @@ app.*.symbols
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock
!.vscode/settings.json
# Monorepo
.cipd
.gclient
.gclient_entries
.python-version
.gclient_previous_custom_vars
.gclient_previous_sync_commits

1082
DEPS Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@ analyzer:
- "bin/cache/**"
# Ignore protoc generated files
- "dev/conductor/lib/proto/*"
- "engine/**"
formatter:
page_width: 100

View File

@@ -1881,6 +1881,7 @@ Future<List<File>> _gitFiles(String workingDirectory, {bool runSilently = true})
assert(filenames.last.isEmpty); // git ls-files gives a trailing blank 0x00
filenames.removeLast();
return filenames
.where((String filename) => !filename.startsWith('engine/'))
.map<File>((String filename) => File(path.join(workingDirectory, filename)))
.toList();
}

10
engine/README.md Normal file
View File

@@ -0,0 +1,10 @@
# Flutter Engine
## `gclient` bootstrap
Flutter engine uses `gclient` to manage dependencies.
If you've already cloned the flutter repository:
1. Copy one of the `engine/scripts/*.gclient` to the root folder as `.gclient`
2. run `gclient sync`

View File

@@ -0,0 +1,14 @@
# Copy this file to the root of your flutter checkout to bootstrap gclient
# or just run gclient sync in an empty directory with this file.
solutions = [
{
"custom_vars": {
"use_rbe": True,
},
"deps_file": "DEPS",
"managed": False,
"name": ".",
"safesync_url": "",
"url": "https://github.com/flutter/flutter.git",
},
]

View File

@@ -0,0 +1,12 @@
# Copy this file to the root of your flutter checkout to bootstrap gclient
# or just run gclient sync in an empty directory with this file.
solutions = [
{
"custom_deps": {},
"deps_file": "DEPS",
"managed": False,
"name": ".",
"safesync_url": "",
"url": "https://github.com/flutter/flutter.git",
},
]

7
engine/src/.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
## This page intentionally left blank. ##
#
# Workaround for VS2013 automatically creating .gitattributes files with
# default settings that we don't want.
# See also:
# http://connect.microsoft.com/VisualStudio/feedback/details/804948/inappropriately-creates-gitattributes-file
# http://crbug.com/342064

40
engine/src/.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
# commonly generated files
*.pyc
*~
.*.sw?
.ccls-cache
.checkstyle
.clangd
.classpath
.cproject
.DS_Store
.gdb_history
.gdbinit
.idea
.ignore
.landmines
.packages
.project
.pub
.pydevproject
.vscode
.cache
compile_commands.json
cscope.*
Session.vim
tags
Thumbs.db
# directories pulled in via deps or hooks
/buildtools/
/gradle/
/ios_tools/
/out/
/third_party/
/build/secondary/third_party/protobuf/
# This is where the gclient hook downloads the Fuchsia SDK and toolchain.
/fuchsia/
# Override higher level build ignore
!build/

27
engine/src/.gn Normal file
View File

@@ -0,0 +1,27 @@
# This file is used by the experimental meta-buildsystem in src/tools/gn to
# find the root of the source tree and to set startup options.
# Use vpython3 from depot_tools for exec_script() calls.
# See `gn help dotfile` for details.
script_executable = "vpython3"
# The location of the build configuration file.
buildconfig = "//build/config/BUILDCONFIG.gn"
# The secondary source root is a parallel directory tree where
# GN build files are placed when they can not be placed directly
# in the source tree, e.g. for third party source trees.
secondary_source = "//flutter/build/secondary/"
# The set of targets known to pass 'gn check'. When all targets pass, remove
# this.
check_targets = [
"//flutter/common/*",
"//flutter/display_list/*",
"//flutter/flow/*",
"//flutter/fml/*",
"//flutter/lib/*",
"//flutter/impeller/*",
"//flutter/runtime/*",
"//flutter/shell/*",
]

20
engine/src/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"clangd.path": "${workspaceFolder}/buildtools/mac-arm64/clang/bin/clangd",
"clangd.arguments": [
"--compile-commands-dir=${workspaceFolder}/../out/host_debug_unopt_arm64"
],
"clang-format.executable": "${workspaceRoot}/buildtools/mac-arm64/clang/bin/clang-format",
// "clangd.path": "flutter/buildtools/mac-arm64/clang/bin/clangd",
// "clangd.arguments": [
// "--compile-commands-dir=out/host_debug_unopt_arm64"
// ],
// "clang-format.executable": "flutter/buildtools/mac-arm64/clang/bin/clang-format",
"search.followSymlinks": true,
"search.quickOpen.includeHistory": true,
"search.quickOpen.includeSymbols": false,
"search.useIgnoreFiles": false,
"editor.tabSize": 2,
}

9
engine/src/AUTHORS Normal file
View File

@@ -0,0 +1,9 @@
# Below is a list of people and organizations that have contributed
# to the Flutter project. Names should be added to the list like so:
#
# Name/Organization <email address>
Google Inc.
Jim Simon <jim.j.simon@gmail.com>
The Fuchsia Authors
Hidenori Matsubayashi <Hidenori.Matsubayashi@sony.com>

22
engine/src/BUILD.gn Normal file
View File

@@ -0,0 +1,22 @@
# 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.
group("default") {
testonly = true
if (target_os == "wasm") {
deps = [ "//flutter/wasm" ]
} else {
deps = [ "//flutter" ]
}
}
group("dist") {
testonly = true
if (target_os == "wasm") {
deps = [ "//flutter/wasm" ]
} else {
deps = [ "//flutter:dist" ]
}
}

9
engine/src/CODEOWNERS Normal file
View File

@@ -0,0 +1,9 @@
# Below is a list of Flutter hackers GitHub handles who are
# suggested reviewers for contributions to this repository.
#
# These names are just suggestions. It is fine to have your changes
# reviewed by someone else.
#
# Use git ls-files '<pattern>' without a / prefix to see the list of matching files.
/build/config/ios/** @jmagman

27
engine/src/LICENSE Normal file
View File

@@ -0,0 +1,27 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

14
engine/src/README.md Normal file
View File

@@ -0,0 +1,14 @@
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/flutter/buildroot/badge)](https://api.securityscorecards.dev/projects/github.com/flutter/buildroot)
# buildroot
Build environment for the Flutter engine
This repository is used by the [flutter/engine](https://github.com/flutter/engine) repository.
For instructions on how to use it, see that repository's [CONTRIBUTING.md](https://github.com/flutter/engine/blob/main/CONTRIBUTING.md) file.
To update your checkout to use the latest buildroot, run `gclient sync`.
To submit patches to this buildroot repository, create a branch, push to that branch, then submit a PR on GitHub for that branch.
To point the engine to a new version of buildroot after your patch is merged, update the buildroot hash in the engine's [DEPS file](https://github.com/flutter/engine/blob/main/DEPS).

4
engine/src/build/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Generated file containing information about the VS toolchain on Windows
win_toolchain.json
new_win_toolchain.json
/linux/debian_*-sysroot/

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
#
# Copyright 2016 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.
"""Create a JAR incorporating all the components required to build a Flutter application"""
import optparse
import os
import sys
import zipfile
from util import build_utils
def main(args):
args = build_utils.ExpandFileArgs(args)
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
parser.add_option('--output', help='Path to output jar.')
parser.add_option('--output_native_jar', help='Path to output native library jar.')
parser.add_option('--dist_jar', help='Flutter shell Java code jar.')
parser.add_option('--native_lib', action='append', help='Native code library.')
parser.add_option('--android_abi', help='Native code ABI.')
parser.add_option('--asset_dir', help='Path to assets.')
options, _ = parser.parse_args(args)
build_utils.CheckOptions(options, parser, [
'output', 'dist_jar', 'native_lib', 'android_abi'
])
input_deps = []
with zipfile.ZipFile(options.output, 'w', zipfile.ZIP_DEFLATED) as out_zip:
input_deps.append(options.dist_jar)
with zipfile.ZipFile(options.dist_jar, 'r') as dist_zip:
for dist_file in dist_zip.infolist():
if dist_file.filename.endswith('.class'):
out_zip.writestr(dist_file.filename, dist_zip.read(dist_file.filename))
for native_lib in options.native_lib:
input_deps.append(native_lib)
out_zip.write(native_lib,
'lib/%s/%s' % (options.android_abi, os.path.basename(native_lib)))
if options.asset_dir:
for asset_file in os.listdir(options.asset_dir):
input_deps.append(asset_file)
out_zip.write(os.path.join(options.asset_dir, asset_file),
'assets/flutter_shared/%s' % asset_file)
if options.output_native_jar:
with zipfile.ZipFile(options.output_native_jar, 'w', zipfile.ZIP_DEFLATED) as out_zip:
for native_lib in options.native_lib:
out_zip.write(native_lib,
'lib/%s/%s' % (options.android_abi, os.path.basename(native_lib)))
if options.depfile:
build_utils.WriteDepfile(
options.depfile,
input_deps + build_utils.GetPythonDependencies())
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python3
#
# Copyright 2013 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 fnmatch
import optparse
import os
import sys
from util import build_utils
from util import md5_check
def Jar(class_files, classes_dir, jar_path, jar_bin, manifest_file=None, additional_jar_files=None):
jar_path = os.path.abspath(jar_path)
# The paths of the files in the jar will be the same as they are passed in to
# the command. Because of this, the command should be run in
# options.classes_dir so the .class file paths in the jar are correct.
jar_cwd = classes_dir
class_files_rel = [os.path.relpath(f, jar_cwd) for f in class_files]
jar_cmd = [jar_bin, 'cf0', jar_path]
if manifest_file:
jar_cmd[1] += 'm'
jar_cmd.append(os.path.abspath(manifest_file))
jar_cmd.extend(class_files_rel)
if additional_jar_files:
jar_cmd.extend(additional_jar_files)
with build_utils.TempDir() as temp_dir:
empty_file = os.path.join(temp_dir, '.empty')
build_utils.Touch(empty_file)
jar_cmd.append(os.path.relpath(empty_file, jar_cwd))
record_path = '%s.md5.stamp' % jar_path
md5_check.CallAndRecordIfStale(
lambda: build_utils.CheckOutput(jar_cmd, cwd=jar_cwd),
record_path=record_path,
input_paths=class_files,
input_strings=jar_cmd,
force=not os.path.exists(jar_path),
)
build_utils.Touch(jar_path, fail_if_missing=True)
def JarDirectory(classes_dir, excluded_classes, jar_path, jar_bin, manifest_file=None, additional_jar_files=None):
class_files = build_utils.FindInDirectory(classes_dir, '*.class')
for exclude in excluded_classes:
class_files = [f for f in class_files if not fnmatch.fnmatch(f, exclude)]
Jar(class_files, classes_dir, jar_path, jar_bin, manifest_file=manifest_file,
additional_jar_files=additional_jar_files)
def main():
parser = optparse.OptionParser()
parser.add_option('--classes-dir', help='Directory containing .class files.')
parser.add_option('--jar-path', help='Jar output path.')
parser.add_option('--excluded-classes',
help='List of .class file patterns to exclude from the jar.')
parser.add_option('--stamp', help='Path to touch on success.')
parser.add_option(
'--jar-bin',
default='jar',
help='The jar binary. If empty, the jar binary is resolved from PATH.')
options, _ = parser.parse_args()
if options.excluded_classes:
excluded_classes = build_utils.ParseGypList(options.excluded_classes)
else:
excluded_classes = []
JarDirectory(options.classes_dir,
excluded_classes,
options.jar_path,
options.jar_bin)
if options.stamp:
build_utils.Touch(options.stamp)
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,340 @@
#!/usr/bin/env python3
#
# Copyright 2013 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 fnmatch
import optparse
import os
import shutil
import re
import sys
import textwrap
from util import ansi_colors
from util import build_utils
from util import md5_check
import jar
def ColorJavacOutput(output):
fileline_prefix = r'(?P<fileline>(?P<file>[-.\w/\\]+.java):(?P<line>[0-9]+):)'
warning_re = re.compile(
fileline_prefix + r'(?P<full_message> warning: (?P<message>.*))$')
error_re = re.compile(
fileline_prefix + r'(?P<full_message> (?P<message>.*))$')
marker_re = re.compile(r'\s*(?P<marker>\^)\s*$')
warning_color = ['full_message', ansi_colors.FOREGROUND_YELLOW + ansi_colors.STYLE_DIM]
error_color = ['full_message', ansi_colors.FOREGROUND_MAGENTA + ansi_colors.STYLE_BRIGHT]
marker_color = ['marker', ansi_colors.FOREGROUND_BLUE + ansi_colors.STYLE_BRIGHT]
def Colorize(line, regex, color):
match = regex.match(line)
start = match.start(color[0])
end = match.end(color[0])
return (line[:start]
+ color[1] + line[start:end]
+ ansi_colors.FOREGROUND_RESET + ansi_colors.STYLE_RESET_ALL
+ line[end:])
def ApplyColor(line):
if warning_re.match(line):
line = Colorize(line, warning_re, warning_color)
elif error_re.match(line):
line = Colorize(line, error_re, error_color)
elif marker_re.match(line):
line = Colorize(line, marker_re, marker_color)
return line
return '\n'.join(map(ApplyColor, output.split('\n')))
def DoJavac(
bootclasspath, classpath, classes_dir, chromium_code,
javac_bin, java_version, java_files):
"""Runs javac.
Builds |java_files| with the provided |classpath| and puts the generated
.class files into |classes_dir|. If |chromium_code| is true, extra lint
checking will be enabled.
"""
jar_inputs = []
for path in classpath:
if os.path.exists(path + '.TOC'):
jar_inputs.append(path + '.TOC')
else:
jar_inputs.append(path)
javac_args = [
'-g',
# Chromium only allows UTF8 source files. Being explicit avoids
# javac pulling a default encoding from the user's environment.
'-encoding', 'UTF-8',
'-classpath', ':'.join(classpath),
'-d', classes_dir,
# TODO(camsim99): Fix deprecations:
# https://github.com/flutter/flutter/issues/98602.
'-Xlint:-deprecation']
if bootclasspath:
javac_args.extend([
'-bootclasspath', ':'.join(bootclasspath),
'-source', java_version,
'-target', java_version,
])
if chromium_code:
javac_args.extend(['-Xlint:unchecked'])
else:
# XDignore.symbol.file makes javac compile against rt.jar instead of
# ct.sym. This means that using a java internal package/class will not
# trigger a compile warning or error.
javac_args.extend(['-XDignore.symbol.file'])
javac_cmd = [javac_bin] + javac_args + java_files
def Compile():
build_utils.CheckOutput(
javac_cmd,
print_stdout=chromium_code,
stderr_filter=ColorJavacOutput)
record_path = os.path.join(classes_dir, 'javac.md5.stamp')
md5_check.CallAndRecordIfStale(
Compile,
record_path=record_path,
input_paths=java_files + jar_inputs,
input_strings=javac_cmd)
_MAX_MANIFEST_LINE_LEN = 72
def CreateManifest(manifest_path, classpath, main_class=None,
manifest_entries=None):
"""Creates a manifest file with the given parameters.
This generates a manifest file that compiles with the spec found at
http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#JAR_Manifest
Args:
manifest_path: The path to the manifest file that should be created.
classpath: The JAR files that should be listed on the manifest file's
classpath.
main_class: If present, the class containing the main() function.
manifest_entries: If present, a list of (key, value) pairs to add to
the manifest.
"""
output = ['Manifest-Version: 1.0']
if main_class:
output.append('Main-Class: %s' % main_class)
if manifest_entries:
for k, v in manifest_entries:
output.append('%s: %s' % (k, v))
if classpath:
sanitized_paths = []
for path in classpath:
sanitized_paths.append(os.path.basename(path.strip('"')))
output.append('Class-Path: %s' % ' '.join(sanitized_paths))
output.append('Created-By: ')
output.append('')
wrapper = textwrap.TextWrapper(break_long_words=True,
drop_whitespace=False,
subsequent_indent=' ',
width=_MAX_MANIFEST_LINE_LEN - 2)
output = '\r\n'.join(w for l in output for w in wrapper.wrap(l))
with open(manifest_path, 'w') as f:
f.write(output)
def main(argv):
argv = build_utils.ExpandFileArgs(argv)
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
parser.add_option(
'--src-gendirs',
help='Directories containing generated java files.')
parser.add_option(
'--java-srcjars',
action='append',
default=[],
help='List of srcjars to include in compilation.')
parser.add_option(
'--bootclasspath',
action='append',
default=[],
help='Boot classpath for javac. If this is specified multiple times, '
'they will all be appended to construct the classpath.')
parser.add_option(
'--classpath',
action='append',
help='Classpath for javac. If this is specified multiple times, they '
'will all be appended to construct the classpath.')
parser.add_option(
'--javac-includes',
help='A list of file patterns. If provided, only java files that match'
'one of the patterns will be compiled.')
parser.add_option(
'--jar-excluded-classes',
default='',
help='List of .class file patterns to exclude from the jar.')
parser.add_option(
'--chromium-code',
type='int',
help='Whether code being compiled should be built with stricter '
'warnings for chromium code.')
parser.add_option(
'--javac-bin',
default='javac',
help='The javac binary. If empty, the javac binary is resolved from PATH.')
parser.add_option(
'--jar-bin',
default='jar',
help='The jar binary. If empty, the jar binary is resolved from PATH.')
parser.add_option(
'--java-version',
default='1.8',
help='The source and target versions passed to javac.')
parser.add_option(
'--classes-dir',
help='Directory for compiled .class files.')
parser.add_option('--jar-path', help='Jar output path.')
parser.add_option('--jar-source-path', help='Source jar output path.')
parser.add_option(
'--jar-source-base-dir',
help='Base directory for the source files included in the output source jar.')
parser.add_option(
'--main-class',
help='The class containing the main method.')
parser.add_option(
'--manifest-entry',
action='append',
help='Key:value pairs to add to the .jar manifest.')
parser.add_option(
'--additional-jar-files',
dest='additional_jar_files',
action='append',
help='Additional files to package into jar. By default, only Java .class '
'files are packaged into the jar.')
parser.add_option('--stamp', help='Path to touch on success.')
options, args = parser.parse_args(argv)
if options.main_class and not options.jar_path:
parser.error('--main-class requires --jar-path')
bootclasspath = []
for arg in options.bootclasspath:
bootclasspath += build_utils.ParseGypList(arg)
classpath = []
for arg in options.classpath:
classpath += build_utils.ParseGypList(arg)
java_srcjars = []
for arg in options.java_srcjars:
java_srcjars += build_utils.ParseGypList(arg)
java_files = args
if options.src_gendirs:
src_gendirs = build_utils.ParseGypList(options.src_gendirs)
java_files += build_utils.FindInDirectories(src_gendirs, '*.java')
additional_jar_files = []
for arg in options.additional_jar_files or []:
additional_jar_files += build_utils.ParseGypList(arg)
input_files = bootclasspath + classpath + java_srcjars + java_files
with build_utils.TempDir() as temp_dir:
classes_dir = os.path.join(temp_dir, 'classes')
os.makedirs(classes_dir)
if java_srcjars:
java_dir = os.path.join(temp_dir, 'java')
os.makedirs(java_dir)
for srcjar in java_srcjars:
build_utils.ExtractAll(srcjar, path=java_dir, pattern='*.java')
java_files += build_utils.FindInDirectory(java_dir, '*.java')
if options.javac_includes:
javac_includes = build_utils.ParseGypList(options.javac_includes)
filtered_java_files = []
for f in java_files:
for include in javac_includes:
if fnmatch.fnmatch(f, include):
filtered_java_files.append(f)
break
java_files = filtered_java_files
if len(java_files) != 0:
DoJavac(
bootclasspath,
classpath,
classes_dir,
options.chromium_code,
options.javac_bin,
options.java_version,
java_files)
if options.jar_path:
if options.main_class or options.manifest_entry:
if options.manifest_entry:
entries = [e.split(":") for e in options.manifest_entry]
else:
entries = []
manifest_file = os.path.join(temp_dir, 'manifest')
CreateManifest(manifest_file, classpath, options.main_class, entries)
else:
manifest_file = None
if options.additional_jar_files:
for f in additional_jar_files:
# Also make the additional files available at the relative paths
# matching their original locations.
shutil.copyfile(f, os.path.join(
classes_dir, os.path.relpath(f, options.jar_source_base_dir)))
additional_jar_files = [os.path.relpath(
f, options.jar_source_base_dir) for f in additional_jar_files]
jar.JarDirectory(classes_dir,
build_utils.ParseGypList(options.jar_excluded_classes),
options.jar_path,
options.jar_bin,
manifest_file=manifest_file,
additional_jar_files=additional_jar_files)
if options.jar_source_path:
jar.Jar(java_files, options.jar_source_base_dir, options.jar_source_path, options.jar_bin)
if options.classes_dir:
# Delete the old classes directory. This ensures that all .class files in
# the output are actually from the input .java files. For example, if a
# .java file is deleted or an inner class is removed, the classes
# directory should not contain the corresponding old .class file after
# running this action.
build_utils.DeleteDirectory(options.classes_dir)
shutil.copytree(classes_dir, options.classes_dir)
if options.depfile:
build_utils.WriteDepfile(
options.depfile,
input_files + build_utils.GetPythonDependencies())
if options.stamp:
build_utils.Touch(options.stamp)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

View File

@@ -0,0 +1,4 @@
# Copyright (c) 2012 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.

View File

@@ -0,0 +1,14 @@
# Copyright 2013 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.
# The following are unicode (string) constants that were previously defined in
# "colorama". They are inlined here to avoid a dependency, as this is the only
# call site and it's unlikely we'll need to change them.
FOREGROUND_YELLOW = '\x1b[33m'
FOREGROUND_MAGENTA = '\x1b[35m'
FOREGROUND_BLUE = '\x1b[34m'
FOREGROUND_RESET = '\x1b[39m'
STYLE_RESET_ALL = '\x1b[0m'
STYLE_DIM = '\x1b[2m'
STYLE_BRIGHT = '\x1b[1m'

View File

@@ -0,0 +1,396 @@
# Copyright 2013 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 ast
import contextlib
import fnmatch
import json
import os
import pipes
import re
import shlex
import shutil
import subprocess
import sys
import tempfile
import zipfile
# Definition copied from pylib/constants/__init__.py to avoid adding
# a dependency on pylib.
DIR_SOURCE_ROOT = os.environ.get('CHECKOUT_SOURCE_ROOT',
os.path.abspath(os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir, os.pardir)))
# aapt should ignore OWNERS files in addition the default ignore pattern.
AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' +
'!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp')
@contextlib.contextmanager
def TempDir():
dirname = tempfile.mkdtemp()
try:
yield dirname
finally:
shutil.rmtree(dirname)
def MakeDirectory(dir_path):
try:
os.makedirs(dir_path)
except OSError:
pass
def DeleteDirectory(dir_path):
if os.path.exists(dir_path):
shutil.rmtree(dir_path)
def Touch(path, fail_if_missing=False):
if fail_if_missing and not os.path.exists(path):
raise Exception(path + ' doesn\'t exist.')
MakeDirectory(os.path.dirname(path))
with open(path, 'a'):
os.utime(path, None)
def FindInDirectory(directory, filename_filter):
files = []
for root, _dirnames, filenames in os.walk(directory):
matched_files = fnmatch.filter(filenames, filename_filter)
files.extend((os.path.join(root, f) for f in matched_files))
return files
def FindInDirectories(directories, filename_filter):
all_files = []
for directory in directories:
all_files.extend(FindInDirectory(directory, filename_filter))
return all_files
def ParseGnList(gn_string):
return ast.literal_eval(gn_string)
def ParseGypList(gyp_string):
# The ninja generator doesn't support $ in strings, so use ## to
# represent $.
# TODO(cjhopman): Remove when
# https://code.google.com/p/gyp/issues/detail?id=327
# is addressed.
gyp_string = gyp_string.replace('##', '$')
if gyp_string.startswith('['):
return ParseGnList(gyp_string)
return shlex.split(gyp_string)
def CheckOptions(options, parser, required=None):
if not required:
return
for option_name in required:
if getattr(options, option_name) is None:
parser.error('--%s is required' % option_name.replace('_', '-'))
def WriteJson(obj, path, only_if_changed=False):
old_dump = None
if os.path.exists(path):
with open(path, 'r') as oldfile:
old_dump = oldfile.read()
new_dump = json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': '))
if not only_if_changed or old_dump != new_dump:
with open(path, 'w') as outfile:
outfile.write(new_dump)
def ReadJson(path):
with open(path, 'r') as jsonfile:
return json.load(jsonfile)
class CalledProcessError(Exception):
"""This exception is raised when the process run by CheckOutput
exits with a non-zero exit code."""
def __init__(self, cwd, args, output):
super(CalledProcessError, self).__init__()
self.cwd = cwd
self.args = args
self.output = output
def __str__(self):
# A user should be able to simply copy and paste the command that failed
# into their shell.
copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd),
' '.join(map(pipes.quote, self.args)))
return 'Command failed: {}\n{}'.format(copyable_command, self.output)
# This can be used in most cases like subprocess.check_output(). The output,
# particularly when the command fails, better highlights the command's failure.
# If the command fails, raises a build_utils.CalledProcessError.
def CheckOutput(args, cwd=None,
print_stdout=False, print_stderr=True,
stdout_filter=None,
stderr_filter=None,
universal_newlines=True,
fail_func=lambda returncode, stderr: returncode != 0):
if not cwd:
cwd = os.getcwd()
child = subprocess.Popen(args,
universal_newlines=universal_newlines,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
stdout, stderr = child.communicate()
if stdout_filter is not None:
stdout = stdout_filter(stdout)
if stderr_filter is not None:
stderr = stderr_filter(stderr)
if fail_func(child.returncode, stderr):
raise CalledProcessError(cwd, args, stdout + stderr)
if print_stdout:
sys.stdout.write(stdout)
if print_stderr:
sys.stderr.write(stderr)
return stdout
def GetModifiedTime(path):
# For a symlink, the modified time should be the greater of the link's
# modified time and the modified time of the target.
return max(os.lstat(path).st_mtime, os.stat(path).st_mtime)
def IsTimeStale(output, inputs):
if not os.path.exists(output):
return True
output_time = GetModifiedTime(output)
for i in inputs:
if GetModifiedTime(i) > output_time:
return True
return False
def IsDeviceReady():
device_state = CheckOutput(['adb', 'get-state'])
return device_state.strip() == 'device'
def CheckZipPath(name):
if os.path.normpath(name) != name:
raise Exception('Non-canonical zip path: %s' % name)
if os.path.isabs(name):
raise Exception('Absolute zip path: %s' % name)
def ExtractAll(zip_path, path=None, no_clobber=True, pattern=None):
if path is None:
path = os.getcwd()
elif not os.path.exists(path):
MakeDirectory(path)
with zipfile.ZipFile(zip_path) as z:
for name in z.namelist():
if name.endswith('/'):
continue
if pattern is not None:
if not fnmatch.fnmatch(name, pattern):
continue
CheckZipPath(name)
if no_clobber:
output_path = os.path.join(path, name)
if os.path.exists(output_path):
raise Exception(
'Path already exists from zip: %s %s %s'
% (zip_path, name, output_path))
z.extractall(path=path)
def DoZip(inputs, output, base_dir):
with zipfile.ZipFile(output, 'w') as outfile:
for f in inputs:
CheckZipPath(os.path.relpath(f, base_dir))
outfile.write(f, os.path.relpath(f, base_dir))
def ZipDir(output, base_dir):
with zipfile.ZipFile(output, 'w') as outfile:
for root, _, files in os.walk(base_dir):
for f in files:
path = os.path.join(root, f)
archive_path = os.path.relpath(path, base_dir)
CheckZipPath(archive_path)
outfile.write(path, archive_path)
def MergeZips(output, inputs, exclude_patterns=None):
added_names = set()
def Allow(name):
if exclude_patterns is not None:
for p in exclude_patterns:
if fnmatch.fnmatch(name, p):
return False
return True
with zipfile.ZipFile(output, 'w') as out_zip:
for in_file in inputs:
with zipfile.ZipFile(in_file, 'r') as in_zip:
for name in in_zip.namelist():
if name not in added_names and Allow(name):
out_zip.writestr(name, in_zip.read(name))
added_names.add(name)
def PrintWarning(message):
print('WARNING: %s' % message)
def PrintBigWarning(message):
print('***** ' * 8)
PrintWarning(message)
print('***** ' * 8)
def GetSortedTransitiveDependencies(top, deps_func):
"""Gets the list of all transitive dependencies in sorted order.
There should be no cycles in the dependency graph.
Args:
top: a list of the top level nodes
deps_func: A function that takes a node and returns its direct dependencies.
Returns:
A list of all transitive dependencies of nodes in top, in order (a node will
appear in the list at a higher index than all of its dependencies).
"""
def Node(dep):
return (dep, deps_func(dep))
# First: find all deps
unchecked_deps = list(top)
all_deps = set(top)
while unchecked_deps:
dep = unchecked_deps.pop()
new_deps = deps_func(dep).difference(all_deps)
unchecked_deps.extend(new_deps)
all_deps = all_deps.union(new_deps)
# Then: simple, slow topological sort.
sorted_deps = []
unsorted_deps = dict(map(Node, all_deps))
while unsorted_deps:
for library, dependencies in unsorted_deps.items():
if not dependencies.intersection(unsorted_deps.keys()):
sorted_deps.append(library)
del unsorted_deps[library]
return sorted_deps
def GetPythonDependencies():
"""Gets the paths of imported non-system python modules.
A path is assumed to be a "system" import if it is outside of chromium's
src/. The paths will be relative to the current directory.
"""
_ForceLazyModulesToLoad()
module_paths = (m.__file__ for m in sys.modules.values()
if m is not None and hasattr(m, '__file__'))
abs_module_paths = map(os.path.abspath, filter(lambda p: p is not None, module_paths))
assert os.path.isabs(DIR_SOURCE_ROOT)
non_system_module_paths = [
p for p in abs_module_paths if p.startswith(DIR_SOURCE_ROOT)]
def ConvertPycToPy(s):
if s.endswith('.pyc'):
return s[:-1]
return s
non_system_module_paths = map(ConvertPycToPy, non_system_module_paths)
non_system_module_paths = map(os.path.relpath, non_system_module_paths)
return sorted(set(non_system_module_paths))
def _ForceLazyModulesToLoad():
"""Forces any lazily imported modules to fully load themselves.
Inspecting the modules' __file__ attribute causes lazily imported modules
(e.g. from email) to get fully imported and update sys.modules. Iterate
over the values until sys.modules stabilizes so that no modules are missed.
"""
while True:
num_modules_before = len(sys.modules.keys())
for m in sys.modules.values():
if m is not None and hasattr(m, '__file__'):
_ = m.__file__
num_modules_after = len(sys.modules.keys())
if num_modules_before == num_modules_after:
break
def AddDepfileOption(parser):
parser.add_option('--depfile',
help='Path to depfile. This must be specified as the '
'action\'s first output.')
def WriteDepfile(path, dependencies):
with open(path, 'w') as depfile:
depfile.write(path)
depfile.write(': ')
depfile.write(' '.join(dependencies))
depfile.write('\n')
def ExpandFileArgs(args):
"""Replaces file-arg placeholders in args.
These placeholders have the form:
@FileArg(filename:key1:key2:...:keyn)
The value of such a placeholder is calculated by reading 'filename' as json.
And then extracting the value at [key1][key2]...[keyn].
Note: This intentionally does not return the list of files that appear in such
placeholders. An action that uses file-args *must* know the paths of those
files prior to the parsing of the arguments (typically by explicitly listing
them in the action's inputs in build files).
"""
new_args = list(args)
file_jsons = dict()
r = re.compile('@FileArg\((.*?)\)')
for i, arg in enumerate(args):
match = r.search(arg)
if not match:
continue
if match.end() != len(arg):
raise Exception('Unexpected characters after FileArg: ' + arg)
lookup_path = match.group(1).split(':')
file_path = lookup_path[0]
if not file_path in file_jsons:
file_jsons[file_path] = ReadJson(file_path)
expansion = file_jsons[file_path]
for k in lookup_path[1:]:
expansion = expansion[k]
new_args[i] = arg[:match.start()] + str(expansion)
return new_args

View File

@@ -0,0 +1,86 @@
# Copyright 2013 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 hashlib
import os
def CallAndRecordIfStale(
function, record_path=None, input_paths=None, input_strings=None,
force=False):
"""Calls function if the md5sum of the input paths/strings has changed.
The md5sum of the inputs is compared with the one stored in record_path. If
this has changed (or the record doesn't exist), function will be called and
the new md5sum will be recorded.
If force is True, the function will be called regardless of whether the
md5sum is out of date.
"""
if not input_paths:
input_paths = []
if not input_strings:
input_strings = []
md5_checker = _Md5Checker(
record_path=record_path,
input_paths=input_paths,
input_strings=input_strings)
if force or md5_checker.IsStale():
function()
md5_checker.Write()
def _UpdateMd5ForFile(md5, path, block_size=2**16):
with open(path, 'rb') as infile:
while True:
data = infile.read(block_size)
if not data:
break
md5.update(data)
def _UpdateMd5ForDirectory(md5, dir_path):
for root, _, files in os.walk(dir_path):
for f in files:
_UpdateMd5ForFile(md5, os.path.join(root, f))
def _UpdateMd5ForPath(md5, path):
if os.path.isdir(path):
_UpdateMd5ForDirectory(md5, path)
else:
_UpdateMd5ForFile(md5, path)
class _Md5Checker(object):
def __init__(self, record_path=None, input_paths=None, input_strings=None):
if not input_paths:
input_paths = []
if not input_strings:
input_strings = []
assert record_path.endswith('.stamp'), (
'record paths must end in \'.stamp\' so that they are easy to find '
'and delete')
self.record_path = record_path
md5 = hashlib.md5()
for i in sorted(input_paths):
_UpdateMd5ForPath(md5, i)
for s in input_strings:
md5.update(s.encode('utf-8'))
self.new_digest = md5.hexdigest()
self.old_digest = ''
if os.path.exists(self.record_path):
with open(self.record_path, 'r') as old_record:
self.old_digest = old_record.read()
def IsStale(self):
return self.old_digest != self.new_digest
def Write(self):
with open(self.record_path, 'w') as new_record:
new_record.write(self.new_digest)

View File

@@ -0,0 +1,154 @@
// Copyright (c) 2012 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 adds defines about the platform we're currently building on.
// Operating System:
// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) /
// OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI
// Compiler:
// COMPILER_MSVC / COMPILER_GCC
// Processor:
// ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64)
// ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
#ifndef BUILD_BUILD_CONFIG_H_
#define BUILD_BUILD_CONFIG_H_
// A set of macros to use for platform detection.
#if defined(__native_client__)
// __native_client__ must be first, so that other OS_ defines are not set.
#define OS_NACL 1
// OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI.
// PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build
// mode, while it does not in SFI build mode.
#if defined(__native_client_nonsfi__)
#define OS_NACL_NONSFI
#else
#define OS_NACL_SFI
#endif
#elif defined(ANDROID)
#define OS_ANDROID 1
#elif defined(__APPLE__)
// only include TargetConditions after testing ANDROID as some android builds
// on mac don't have this header available and it's not needed unless the target
// is really mac/ios.
#include <TargetConditionals.h>
#define OS_MACOSX 1
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#define OS_IOS 1
#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#elif defined(__linux__)
#define OS_LINUX 1
// include a system header to pull in features.h for glibc/uclibc macros.
#include <unistd.h>
#if defined(__GLIBC__) && !defined(__UCLIBC__)
// we really are using glibc, not uClibc pretending to be glibc
#define LIBC_GLIBC 1
#endif
#elif defined(_WIN32)
#define OS_WIN 1
#define TOOLKIT_VIEWS 1
#elif defined(__FreeBSD__)
#define OS_FREEBSD 1
#elif defined(__OpenBSD__)
#define OS_OPENBSD 1
#elif defined(__sun)
#define OS_SOLARIS 1
#elif defined(__QNXNTO__)
#define OS_QNX 1
#else
#error Please add support for your platform in build/build_config.h
#endif
#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS)
#error Cannot use both OpenSSL and NSS for certificates
#endif
// For access to standard BSD features, use OS_BSD instead of a
// more specific macro.
#if defined(OS_FREEBSD) || defined(OS_OPENBSD)
#define OS_BSD 1
#endif
// For access to standard POSIXish features, use OS_POSIX instead of a
// more specific macro.
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \
defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \
defined(OS_NACL) || defined(OS_QNX)
#define OS_POSIX 1
#endif
// Use tcmalloc
#if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \
!defined(NO_TCMALLOC)
#define USE_TCMALLOC 1
#endif
// Compiler detection.
#if defined(__GNUC__)
#define COMPILER_GCC 1
#elif defined(_MSC_VER)
#define COMPILER_MSVC 1
#else
#error Please add support for your compiler in build/build_config.h
#endif
// Processor architecture detection. For more info on what's defined, see:
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
// http://www.agner.org/optimize/calling_conventions.pdf
// or with gcc, run: "echo | gcc -E -dM -"
#if defined(_M_X64) || defined(__x86_64__)
#define ARCH_CPU_X86_FAMILY 1
#define ARCH_CPU_X86_64 1
#define ARCH_CPU_64_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
#elif defined(_M_IX86) || defined(__i386__)
#define ARCH_CPU_X86_FAMILY 1
#define ARCH_CPU_X86 1
#define ARCH_CPU_32_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
#elif defined(__ARMEL__)
#define ARCH_CPU_ARM_FAMILY 1
#define ARCH_CPU_ARMEL 1
#define ARCH_CPU_32_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCH_CPU_ARM_FAMILY 1
#define ARCH_CPU_ARM64 1
#define ARCH_CPU_64_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
#elif defined(__pnacl__)
#define ARCH_CPU_32_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
#else
#error Please add support for your architecture in build/build_config.h
#endif
// Type detection for wchar_t.
#if defined(OS_WIN)
#define WCHAR_T_IS_UTF16
#elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \
(__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
#define WCHAR_T_IS_UTF32
#elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \
(__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
// compile in this mode (in particular, Chrome doesn't). This is intended for
// other projects using base who manage their own dependencies and make sure
// short wchar works for them.
#define WCHAR_T_IS_UTF16
#else
#error Please add support for your compiler in build/build_config.h
#endif
#if defined(OS_ANDROID)
// The compiler thinks std::string::const_iterator and "const char*" are
// equivalent types.
#define STD_STRING_ITERATOR_IS_CHAR_POINTER
// The compiler thinks base::string16::const_iterator and "char16*" are
// equivalent types.
#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER
#endif
#endif // BUILD_BUILD_CONFIG_H_

111
engine/src/build/clobber.py Executable file
View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python3
#
# Copyright 2015 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 script provides methods for clobbering build directories."""
import argparse
import os
import shutil
import sys
def extract_gn_build_commands(build_ninja_file):
"""Extracts from a build.ninja the commands to run GN.
The commands to run GN are the gn rule and build.ninja build step at the
top of the build.ninja file. We want to keep these when deleting GN builds
since we want to preserve the command-line flags to GN.
On error, returns the empty string."""
result = ""
with open(build_ninja_file, 'r') as f:
# Read until the second blank line. The first thing GN writes to the file
# is the "rule gn" and the second is the section for "build build.ninja",
# separated by blank lines.
num_blank_lines = 0
while num_blank_lines < 2:
line = f.readline()
if len(line) == 0:
return '' # Unexpected EOF.
result += line
if line[0] == '\n':
num_blank_lines = num_blank_lines + 1
return result
def delete_build_dir(build_dir):
# GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
if not os.path.exists(build_ninja_d_file):
shutil.rmtree(build_dir)
return
# GN builds aren't automatically regenerated when you sync. To avoid
# messing with the GN workflow, erase everything but the args file, and
# write a dummy build.ninja file that will automatically rerun GN the next
# time Ninja is run.
build_ninja_file = os.path.join(build_dir, 'build.ninja')
build_commands = extract_gn_build_commands(build_ninja_file)
try:
gn_args_file = os.path.join(build_dir, 'args.gn')
with open(gn_args_file, 'r') as f:
args_contents = f.read()
except IOError:
args_contents = ''
shutil.rmtree(build_dir)
# Put back the args file (if any).
os.mkdir(build_dir)
if args_contents != '':
with open(gn_args_file, 'w') as f:
f.write(args_contents)
# Write the build.ninja file sufficiently to regenerate itself.
with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
if build_commands != '':
f.write(build_commands)
else:
# Couldn't parse the build.ninja file, write a default thing.
f.write('''rule gn
command = gn -q gen //out/%s/
description = Regenerating ninja files
build build.ninja: gn
generator = 1
depfile = build.ninja.d
''' % (os.path.split(build_dir)[1]))
# Write a .d file for the build which references a nonexistant file. This
# will make Ninja always mark the build as dirty.
with open(build_ninja_d_file, 'w') as f:
f.write('build.ninja: nonexistant_file.gn\n')
def clobber(out_dir):
"""Clobber contents of build directory.
Don't delete the directory itself: some checkouts have the build directory
mounted."""
for f in os.listdir(out_dir):
path = os.path.join(out_dir, f)
if os.path.isfile(path):
os.unlink(path)
elif os.path.isdir(path):
delete_build_dir(path)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('out_dir', help='The output directory to clobber')
args = parser.parse_args()
clobber(args.out_dir)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,188 @@
# 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.
# This file introduces two related templates that act like action and
# action_foreach but instead of running a Python script, it will compile a
# given tool in the host toolchain and run that (either once or over the list
# of inputs, depending on the variant).
#
# Parameters
#
# tool (required)
# [label] Label of the tool to run. This should be an executable, and
# this label should not include a toolchain (anything in parens). The
# host compile of this tool will be used.
#
# outputs (required)
# [list of files] Like the outputs of action (if using "compiled_action",
# this would be just the list of outputs), or action_foreach (if using
# "compiled_action_foreach", this would contain source expansions mapping
# input to output files).
#
# args (required)
# [list of strings] Same meaning as action/action_foreach.
#
# inputs (optional)
# Files the binary takes as input. The step will be re-run whenever any
# of these change. If inputs is empty, the step will run only when the
# binary itself changes.
#
# visibility
# deps
# args (all optional)
# Same meaning as action/action_foreach.
#
#
# Example of usage:
#
# compiled_action("run_my_tool") {
# tool = "//tools/something:mytool"
# outputs = [
# "$target_gen_dir/mysource.cc",
# "$target_gen_dir/mysource.h",
# ]
#
# # The tool takes this input.
# inputs = [ "my_input_file.idl" ]
#
# # In this case, the tool takes as arguments the input file and the output
# # build dir (both relative to the "cd" that the script will be run in)
# # and will produce the output files listed above.
# args = [
# rebase_path("my_input_file.idl", root_build_dir),
# "--output-dir", rebase_path(target_gen_dir, root_build_dir),
# ]
# }
#
# You would typically declare your tool like this:
# if (host_toolchain == current_toolchain) {
# executable("mytool") {
# ...
# }
# }
# The if statement around the executable is optional. That says "I only care
# about this target in the host toolchain". Usually this is what you want, and
# saves unnecessarily compiling your tool for the target platform. But if you
# need a target build of your tool as well, just leave off the if statement.
if (host_os == "win") {
_host_executable_suffix = ".exe"
} else {
_host_executable_suffix = ""
}
template("compiled_action") {
assert(defined(invoker.tool), "tool must be defined for $target_name")
assert(defined(invoker.outputs), "outputs must be defined for $target_name")
assert(defined(invoker.args), "args must be defined for $target_name")
assert(!defined(invoker.sources),
"compiled_action doesn't take a sources arg. Use inputs instead.")
action(target_name) {
forward_variables_from(invoker,
[
"visibility",
"metadata",
"testonly",
"pool",
"outputs",
])
script = "//build/gn_run_binary.py"
if (defined(invoker.inputs)) {
inputs = invoker.inputs
} else {
inputs = []
}
if (defined(invoker.toolchain)) {
toolchain = invoker.toolchain
} else {
toolchain = host_toolchain
}
# Constuct the host toolchain version of the tool.
host_tool = invoker.tool + "($toolchain)"
# Get the path to the executable. Currently, this assumes that the tool
# does not specify output_name so that the target name is the name to use.
# If that's not the case, we'll need another argument to the script to
# specify this, since we can't know what the output name is (it might be in
# another file not processed yet).
host_executable =
get_label_info(host_tool, "root_out_dir") + "/" +
get_label_info(host_tool, "name") + _host_executable_suffix
# Add the executable itself as an input.
inputs += [ host_executable ]
deps = [ host_tool ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (defined(invoker.depfile)) {
depfile = invoker.depfile
}
# The script takes as arguments the binary to run, and then the arguments
# to pass it.
args = [ rebase_path(host_executable, root_build_dir) ] + invoker.args
}
}
template("compiled_action_foreach") {
assert(defined(invoker.sources), "sources must be defined for $target_name")
assert(defined(invoker.tool), "tool must be defined for $target_name")
assert(defined(invoker.outputs), "outputs must be defined for $target_name")
assert(defined(invoker.args), "args must be defined for $target_name")
action_foreach(target_name) {
# Otherwise this is a standalone action, define visibility if requested.
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
if (defined(invoker.pool)) {
pool = invoker.pool
}
script = "//build/gn_run_binary.py"
sources = invoker.sources
if (defined(invoker.inputs)) {
inputs = invoker.inputs
} else {
inputs = []
}
outputs = invoker.outputs
# Constuct the host toolchain version of the tool.
host_tool = invoker.tool + "($host_toolchain)"
# Get the path to the executable. Currently, this assumes that the tool
# does not specify output_name so that the target name is the name to use.
# If that's not the case, we'll need another argument to the script to
# specify this, since we can't know what the output name is (it might be in
# another file not processed yet).
host_executable =
get_label_info(host_tool, "root_out_dir") + "/" +
get_label_info(host_tool, "name") + _host_executable_suffix
# Add the executable itself as an input.
inputs += [ host_executable ]
deps = [ host_tool ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (defined(invoker.depfile)) {
depfile = invoker.depfile
}
# The script takes as arguments the binary to run, and then the arguments
# to pass it.
args = [ rebase_path(host_executable, root_build_dir) ] + invoker.args
}
}

View File

@@ -0,0 +1,144 @@
#!/usr/bin/env python3
#
# Copyright (c) 2012 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.
"""Compiler version checking tool for gcc
Print gcc version as XY if you are running gcc X.Y.*.
This is used to tweak build flags for gcc 4.4.
"""
import os
import re
import subprocess
import sys
compiler_version_cache = {} # Map from (compiler, tool) -> version.
def Usage(program_name):
print('%s MODE TOOL' % os.path.basename(program_name))
print('MODE: host or target.')
print('TOOL: assembler or compiler or linker.')
return 1
def ParseArgs(args):
if len(args) != 2:
raise Exception('Invalid number of arguments')
mode = args[0]
tool = args[1]
if mode not in ('host', 'target'):
raise Exception('Invalid mode: %s' % mode)
if tool not in ('assembler', 'compiler', 'linker'):
raise Exception('Invalid tool: %s' % tool)
return mode, tool
def GetEnvironFallback(var_list, default):
"""Look up an environment variable from a possible list of variable names."""
for var in var_list:
if var in os.environ:
return os.environ[var]
return default
def GetVersion(compiler, tool):
tool_output = tool_error = None
cache_key = (compiler, tool)
cached_version = compiler_version_cache.get(cache_key)
if cached_version:
return cached_version
try:
# Note that compiler could be something tricky like "distcc g++".
if tool == "compiler":
compiler = compiler + " -dumpversion"
# 4.6
version_re = re.compile(r"(\d+)\.(\d+)")
elif tool == "assembler":
compiler = compiler + " -Xassembler --version -x assembler -c /dev/null"
# Unmodified: GNU assembler (GNU Binutils) 2.24
# Ubuntu: GNU assembler (GNU Binutils for Ubuntu) 2.22
# Fedora: GNU assembler version 2.23.2
version_re = re.compile(r"^GNU [^ ]+ .* (\d+).(\d+).*?$", re.M)
elif tool == "linker":
compiler = compiler + " -Xlinker --version"
# Using BFD linker
# Unmodified: GNU ld (GNU Binutils) 2.24
# Ubuntu: GNU ld (GNU Binutils for Ubuntu) 2.22
# Fedora: GNU ld version 2.23.2
# Using Gold linker
# Unmodified: GNU gold (GNU Binutils 2.24) 1.11
# Ubuntu: GNU gold (GNU Binutils for Ubuntu 2.22) 1.11
# Fedora: GNU gold (version 2.23.2) 1.11
version_re = re.compile(r"^GNU [^ ]+ .* (\d+).(\d+).*?$", re.M)
else:
raise Exception("Unknown tool %s" % tool)
# Force the locale to C otherwise the version string could be localized
# making regex matching fail.
env = os.environ.copy()
env["LC_ALL"] = "C"
pipe = subprocess.Popen(compiler, shell=True, env=env,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
tool_output, tool_error = pipe.communicate()
if pipe.returncode:
raise subprocess.CalledProcessError(pipe.returncode, compiler)
parsed_output = version_re.match(tool_output)
result = parsed_output.group(1) + parsed_output.group(2)
compiler_version_cache[cache_key] = result
return result
except Exception as e:
if tool_error:
sys.stderr.write(tool_error)
print("compiler_version.py failed to execute:", compiler, file=sys.stderr)
print(e, file=sys.stderr)
return ""
def main(args):
try:
(mode, tool) = ParseArgs(args[1:])
except Exception as e:
sys.stderr.write(e.message + '\n\n')
return Usage(args[0])
ret_code, result = ExtractVersion(mode, tool)
if ret_code == 0:
print(result)
return ret_code
def DoMain(args):
"""Hook to be called from gyp without starting a separate python
interpreter."""
(mode, tool) = ParseArgs(args)
ret_code, result = ExtractVersion(mode, tool)
if ret_code == 0:
return result
raise Exception("Failed to extract compiler version for args: %s" % args)
def ExtractVersion(mode, tool):
# Check if various CXX environment variables exist and use them if they
# exist. The preferences and fallback order is a close approximation of
# GenerateOutputForConfig() in GYP's ninja generator.
# The main difference being not supporting GYP's make_global_settings.
environments = ['CXX_target', 'CXX']
if mode == 'host':
environments = ['CXX_host'] + environments;
compiler = GetEnvironFallback(environments, 'c++')
if compiler:
compiler_version = GetVersion(compiler, tool)
if compiler_version != "":
return (0, compiler_version)
return (1, None)
if __name__ == "__main__":
sys.exit(main(sys.argv))

View File

@@ -0,0 +1,194 @@
# Copyright (c) 2013 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/allocator.gni")
import("//build/config/crypto.gni")
import("//build/config/dcheck_always_on.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
declare_args() {
# When set, turns off the (normally-on) iterator debugging and related stuff
# that is normally turned on for Debug builds. These are generally useful for
# catching bugs but in some cases may cause conflicts or excessive slowness.
disable_iterator_debugging = false
# Set to true to compile with the OpenGL ES 2.0 conformance tests.
internal_gles2_conform_tests = false
}
# TODO(brettw) Most of these should be removed. Instead of global feature
# flags, we should have more modular flags that apply only to a target and its
# dependents. For example, depending on the "x11" meta-target should define
# USE_X11 for all dependents so that everything that could use X11 gets the
# define, but anything that doesn't depend on X11 doesn't see it.
#
# For now we define these globally to match the current GYP build.
config("feature_flags") {
defines = []
if (dcheck_always_on) {
defines += [ "DCHECK_ALWAYS_ON=1" ]
}
if (use_glfw) {
defines += [ "USE_GLFW=1" ]
}
if (use_openssl) {
defines += [ "USE_OPENSSL=1" ]
}
if (use_openssl_certs) {
defines += [ "USE_OPENSSL_CERTS=1" ]
}
if (use_nss_certs) {
defines += [ "USE_NSS_CERTS=1" ]
}
if (is_asan) {
defines += [ "ADDRESS_SANITIZER" ]
}
if (is_lsan) {
defines += [ "LEAK_SANITIZER" ]
}
if (is_tsan) {
defines += [
"THREAD_SANITIZER",
"DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1",
"WTF_USE_DYNAMIC_ANNOTATIONS_NOIMPL=1",
]
}
if (is_msan) {
defines += [ "MEMORY_SANITIZER" ]
}
}
# Debug/release ----------------------------------------------------------------
config("debug") {
defines = [ "_DEBUG" ]
if (is_win) {
if (disable_iterator_debugging) {
# Iterator debugging is enabled by the compiler on debug builds, and we
# have to tell it to turn it off.
defines += [ "_HAS_ITERATOR_DEBUGGING=0" ]
}
} else if (is_linux && !is_android && current_cpu == "x64" &&
!disable_iterator_debugging) {
# Enable libstdc++ debugging facilities to help catch problems early, see
# http://crbug.com/65151 .
# TODO(phajdan.jr): Should we enable this for all of POSIX?
defines += [ "_GLIBCXX_DEBUG=1" ]
}
}
config("release") {
defines = [ "NDEBUG" ]
# Sanitizers.
# TODO(GYP) The GYP build has "release_valgrind_build == 0" for this
# condition. When Valgrind is set up, we need to do the same here.
if (is_tsan) {
defines += [
"DYNAMIC_ANNOTATIONS_ENABLED=1",
"WTF_USE_DYNAMIC_ANNOTATIONS=1",
]
} else {
defines += [ "NVALGRIND" ]
defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=0" ]
}
}
# Default libraries ------------------------------------------------------------
# This config defines the default libraries applied to all targets.
config("default_libs") {
if (is_win) {
# TODO(brettw) this list of defaults should probably be smaller, and
# instead the targets that use the less common ones (e.g. wininet or
# winspool) should include those explicitly.
libs = [
"advapi32.lib",
"comdlg32.lib",
"delayimp.lib",
"dnsapi.lib",
"iphlpapi.lib",
"msimg32.lib",
"odbc32.lib",
"odbccp32.lib",
"ole32.lib",
"oleaut32.lib",
"psapi.lib",
"shell32.lib",
"shlwapi.lib",
"Rpcrt4.lib",
"uuid.lib",
"version.lib",
"wininet.lib",
"winmm.lib",
"winspool.lib",
"ws2_32.lib",
# Please don't add more stuff here. We should actually be making this
# list smaller, since all common things should be covered. If you need
# some extra libraries, please just add a libs = [ "foo.lib" ] to your
# target that needs it.
]
} else if (is_android) {
# Android uses -nostdlib so we need to add even libc here.
libs = [
# TODO(brettw) write a version of this, hopefully we can express this
# without forking out to GCC just to get the library name. The android
# toolchain directory should probably be extracted into a .gni file that
# this file and the android toolchain .gn file can share.
# # Manually link the libgcc.a that the cross compiler uses.
# '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
"c",
"dl",
"m",
]
} else if (is_linux) {
libs = [ "dl" ]
}
}
# Add this config to your target to enable precompiled headers.
#
# On Windows, precompiled headers are done on a per-target basis. If you have
# just a couple of files, the time it takes to precompile (~2 seconds) can
# actually be longer than the time saved. On a Z620, a 100 file target compiles
# about 2 seconds faster with precompiled headers, with greater savings for
# larger targets.
#
# Recommend precompiled headers for targets with more than 50 .cc files.
config("precompiled_headers") {
# TODO(brettw) enable this when GN support in the binary has been rolled.
#if (is_win) {
if (false) {
# This is a string rather than a file GN knows about. It has to match
# exactly what's in the /FI flag below, and what might appear in the source
# code in quotes for an #include directive.
precompiled_header = "build/precompile.h"
# This is a file that GN will compile with the above header. It will be
# implicitly added to the sources (potentially multiple times, with one
# variant for each language used in the target).
precompiled_source = "//build/precompile.cc"
# Force include the header.
cflags = [ "/FI$precompiled_header" ]
}
}
config("symbol_visibility_hidden") {
# Empty but present because this is also present in other buildroots.
# The same config from gcc/BUILD.gn is used instead.
}
config("no_rtti") {
if (is_win) {
cflags_cc = [ "/GR-" ]
} else {
cflags_cc = [ "-fno-rtti" ]
cflags_objcc = cflags_cc
}
}

View File

@@ -0,0 +1,828 @@
# Copyright (c) 2013 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.
# =============================================================================
# PLATFORM SELECTION
# =============================================================================
#
# There are two main things to set: "os" and "cpu". The "toolchain" is the name
# of the GN thing that encodes combinations of these things.
#
# Users typically only set the variables "target_os" and "target_cpu" in "gn
# args", the rest are set up by our build and internal to GN.
#
# There are three different types of each of these things: The "host"
# represents the computer doing the compile and never changes. The "target"
# represents the main thing we're trying to build. The "current" represents
# which configuration is currently being defined, which can be either the
# host, the target, or something completely different (like nacl). GN will
# run the same build file multiple times for the different required
# configuration in the same build.
#
# This gives the following variables:
# - host_os, host_cpu, host_toolchain
# - target_os, target_cpu, default_toolchain
# - current_os, current_cpu, current_toolchain.
#
# Note the default_toolchain isn't symmetrical (you would expect
# target_toolchain). This is because the "default" toolchain is a GN built-in
# concept, and "target" is something our build sets up that's symmetrical with
# its GYP counterpart. Potentially the built-in default_toolchain variable
# could be renamed in the future.
#
# When writing build files, to do something only for the host:
# if (current_toolchain == host_toolchain) { ...
if (target_os == "") {
target_os = host_os
}
if (target_cpu == "") {
if (target_os == "android") {
# If we're building for Android, we should assume that we want to
# build for ARM by default, not the host_cpu (which is likely x64).
# This allows us to not have to specify both target_os and target_cpu
# on the command line.
target_cpu = "arm"
} else {
target_cpu = host_cpu
}
}
if (current_cpu == "") {
current_cpu = target_cpu
}
if (current_os == "") {
if (host_os == "win") {
current_os = "win"
} else {
current_os = target_os
}
}
# =============================================================================
# BUILD FLAGS
# =============================================================================
#
# This block lists input arguments to the build, along with their default
# values.
#
# If a value is specified on the command line, it will overwrite the defaults
# given in a declare_args block, otherwise the default will be used.
#
# YOU SHOULD ALMOST NEVER NEED TO ADD FLAGS TO THIS FILE. GN allows any file in
# the build to declare build flags. If you need a flag for a single component,
# you can just declare it in the corresponding BUILD.gn file. If you need a
# flag in multiple components, there are a few options:
#
# - If your feature is a single target, say //components/foo, and the targets
# depending on foo need to have some define set if foo is enabled: (1) Write
# a declare_args block in foo's BUILD.gn file listing your enable_foo build
# flag. (2) Write a config in that file listing the define, and list that
# config in foo's public_configs. This will propagate that define to all the
# targets depending on foo. (3) When foo is not enabled, just make it expand
# to an empty group (or whatever's appropriate for the "off" state of your
# feature.
#
# - If a semi-random set of targets need to know about a define: (1) In the
# lowest level of the build that knows about this feature, add a declare_args
# block in the build file for your enable flag. (2) Write a config that adds
# a define conditionally based on that build flags. (3) Manually add that
# config to the "configs" applying to the targets that need the define.
#
# - If a semi-random set of targets need to know about the build flag (to do
# file inclusion or exclusion, more than just defines): (1) Write a .gni file
# in the lowest-level directory that knows about the feature. (2) Put the
# declare_args block with your build flag in that .gni file. (3) Import that
# .gni file from the BUILD.gn files that need the flag.
#
# Other advice:
#
# - Use boolean values when possible. If you need a default value that expands
# to some complex thing in the default case (like the location of the
# compiler which would be computed by a script), use a default value of -1 or
# the empty string. Outside of the declare_args block, conditionally expand
# the default value as necessary.
#
# - Use a name like "use_foo" or "is_foo" (whatever is more appropriate for
# your feature) rather than just "foo".
#
# - Write good comments directly above the declaration with no blank line.
# These comments will appear as documentation in "gn args --list".
#
# - Don't call exec_script inside declare_args. This will execute the script
# even if the value is overridden, which is wasteful. See first bullet.
declare_args() {
# How many symbols to include in the build. This affects the performance of
# the build since the symbols are large and dealing with them is slow.
# 2 means regular build with symbols.
# 1 means minimal symbols, usually enough for backtraces only.
# 0 means no symbols.
# -1 means auto-set (off in release, regular in debug).
symbol_level = -1
# Component build.
is_component_build = false
# Official build.
is_official_build = false
# Debug build.
is_debug = true
# Whether we're a traditional desktop unix.
is_desktop_linux = current_os == "linux" && current_os != "chromeos"
# Set to true when compiling with the Clang compiler. Typically this is used
# to configure warnings.
is_clang = current_os == "mac" || current_os == "ios" ||
current_os == "linux" || current_os == "chromeos"
# Compile for Address Sanitizer to find memory bugs.
is_asan = false
# Compile for Leak Sanitizer to find leaks.
is_lsan = false
# Compile for Memory Sanitizer to find uninitialized reads.
is_msan = false
# Compile for Thread Sanitizer to find threading bugs.
is_tsan = false
# Compile for Undefined Behavior Sanitizer.
is_ubsan = false
# protobuf-gn fails to build if this argument isn't defined. This should never
# be set to true, becuase we never build within the Fuchsia tree.
is_fuchsia_tree = false
if (current_os == "chromeos") {
# Allows the target toolchain to be injected as arguments. This is needed
# to support the CrOS build system which supports per-build-configuration
# toolchains.
cros_use_custom_toolchain = false
}
# DON'T ADD MORE FLAGS HERE. Read the comment above.
}
# =============================================================================
# OS DEFINITIONS
# =============================================================================
#
# We set these various is_FOO booleans for convenience in writing OS-based
# conditions.
#
# - is_android, is_chromeos, is_ios, and is_win should be obvious.
# - is_mac is set only for desktop Mac. It is not set on iOS.
# - is_posix is true for mac and any Unix-like system (basically everything
# except Windows).
# - is_linux is true for desktop Linux and ChromeOS, but not Android (which is
# generally too different despite being based on the Linux kernel).
#
# Do not add more is_* variants here for random lesser-used Unix systems like
# aix or one of the BSDs. If you need to check these, just check the
# current_os value directly.
if (current_os == "win") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = false
is_win = true
is_wasm = false
} else if (current_os == "mac") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = true
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "android") {
is_android = true
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "chromeos") {
is_android = false
is_chromeos = true
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = true
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "nacl") {
# current_os == "nacl" will be passed by the nacl toolchain definition.
# It is not set by default or on the command line. We treat is as a
# Posix variant.
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "ios") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = true
is_linux = false
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "linux") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = true
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "fuchsia" || target_os == "fuchsia") {
is_android = false
is_chromeos = false
is_fuchsia = true
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = true
is_win = false
is_wasm = false
} else if (current_os == "wasm") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = false
is_win = false
is_wasm = true
}
is_apple = is_ios || is_mac
# Needed for some third_party build files from Chromium.
is_nacl = false
# Needed for //third_party/angle.
is_castos = false
is_chromecast = false
is_chromeos_lacros = false
ozone_platform_headless = false
# Needed for //flutter/third_party/swiftshader and //third_party/angle.
if (is_linux) {
ozone_platform_x11 = true
ozone_platform_wayland = true
} else {
ozone_platform_x11 = false
ozone_platform_wayland = false
}
default_library_type = "static_library"
# =============================================================================
# BUILD OPTIONS
# =============================================================================
# These Sanitizers all imply using the Clang compiler. On Windows they either
# don't work or work differently.
using_sanitizer = !is_win && (is_asan || is_lsan || is_tsan || is_msan)
if (!is_clang && using_sanitizer) {
is_clang = true
}
use_flutter_cxx = is_clang && (is_linux || is_android || is_mac || is_ios)
if (is_msan && !is_linux) {
assert(false, "Memory sanitizer is only available on Linux.")
}
# =============================================================================
# TARGET DEFAULTS
# =============================================================================
#
# Set up the default configuration for every build target of the given type.
# The values configured here will be automatically set on the scope of the
# corresponding target. Target definitions can add or remove to the settings
# here as needed.
# Holds all configs used for making native executables and libraries, to avoid
# duplication in each target below.
_native_compiler_configs = [
"//build/config:feature_flags",
"//build/config/compiler:compiler",
"//build/config/compiler:cxx_version_default",
"//build/config/compiler:compiler_arm_fpu",
"//build/config/compiler:chromium_code",
"//build/config/compiler:default_include_dirs",
"//build/config/compiler:no_rtti",
"//build/config/compiler:runtime_library",
]
if (use_flutter_cxx) {
_native_compiler_configs += [
"//flutter/third_party/libcxxabi:libcxxabi_config",
"//flutter/third_party/libcxx:libcxx_config",
]
}
if (is_win) {
_native_compiler_configs += [
"//build/config/win:lean_and_mean",
"//build/config/win:nominmax",
"//build/config/win:sdk",
"//build/config/win:unicode",
"//build/config/win:winver",
]
}
if (is_posix) {
_native_compiler_configs += [
"//build/config/gcc:no_exceptions",
"//build/config/gcc:relative_paths",
"//build/config/gcc:symbol_visibility_hidden",
"//build/config:symbol_visibility_hidden",
]
}
if (is_linux) {
_native_compiler_configs += [ "//build/config/linux:sdk" ]
} else if (is_mac) {
_native_compiler_configs += [ "//build/config/mac:sdk" ]
} else if (is_ios) {
_native_compiler_configs += [ "//build/config/ios:sdk" ]
} else if (is_android) {
_native_compiler_configs += [ "//build/config/android:sdk" ]
}
if (is_clang) {
_native_compiler_configs += [ "//build/config/clang:extra_warnings" ]
_native_compiler_configs += [ "//build/config/clang:find_bad_constructs" ]
}
# Optimizations and debug checking.
if (is_debug) {
_native_compiler_configs += [ "//build/config:debug" ]
_default_optimization_config = "//build/config/compiler:no_optimize"
} else {
_native_compiler_configs += [ "//build/config:release" ]
_default_optimization_config = "//build/config/compiler:optimize"
}
_native_compiler_configs += [ _default_optimization_config ]
# zlib's BUILD.gn expects to have this config among default configs.
_native_compiler_configs += [ "//build/config/compiler:default_optimization" ]
# If it wasn't manually set, set to an appropriate default.
if (symbol_level == -1) {
# Linux is slowed by having symbols as part of the target binary, whereas
# Mac and Windows have them separate, so in Release Linux, default them off.
# Wasm we definitely want to strip symbols in release mode because binary
# size is paramount.
if (is_debug || (!is_linux && !is_wasm)) {
symbol_level = 2
} else if (is_asan || is_lsan || is_tsan || is_msan) {
# Sanitizers require symbols for filename suppressions to work.
symbol_level = 1
} else {
symbol_level = 0
}
}
# Symbol setup.
if (symbol_level == 2) {
_default_symbols_config = "//build/config/compiler:symbols"
} else if (symbol_level == 1) {
_default_symbols_config = "//build/config/compiler:minimal_symbols"
} else if (symbol_level == 0) {
_default_symbols_config = "//build/config/compiler:no_symbols"
} else {
assert(false, "Bad value for symbol_level.")
}
_native_compiler_configs += [ _default_symbols_config ]
# Windows linker setup for EXEs and DLLs.
if (is_win) {
_windows_linker_configs = [
"//build/config/win:default_incremental_linking",
"//build/config/win:sdk_link",
"//build/config/win:common_linker_setup",
# Default to console-mode apps. Most of our targets are tests and such
# that shouldn't use the windows subsystem.
"//build/config/win:console",
]
}
# Executable defaults.
_executable_configs =
_native_compiler_configs + [ "//build/config:default_libs" ]
if (is_win) {
_executable_configs += _windows_linker_configs
} else if (is_mac) {
_executable_configs += [
"//build/config/mac:mac_dynamic_flags",
"//build/config/mac:mac_executable_flags",
]
} else if (is_linux || is_android) {
_executable_configs += [ "//build/config/gcc:executable_ldconfig" ]
if (is_android) {
_executable_configs += [ "//build/config/android:executable_config" ]
}
}
set_defaults("executable") {
configs = _executable_configs
}
# Static library defaults.
set_defaults("static_library") {
configs = _native_compiler_configs
}
# Shared library defaults (also for components in component mode).
_shared_library_configs =
_native_compiler_configs + [ "//build/config:default_libs" ]
if (is_win) {
_shared_library_configs += _windows_linker_configs
} else if (is_mac) {
_shared_library_configs += [ "//build/config/mac:mac_dynamic_flags" ]
}
set_defaults("shared_library") {
configs = _shared_library_configs
}
if (is_component_build) {
set_defaults("component") {
configs = _shared_library_configs
}
}
# Source set defaults (also for components in non-component mode).
set_defaults("source_set") {
configs = _native_compiler_configs
}
if (!is_component_build) {
set_defaults("component") {
configs = _native_compiler_configs
}
}
# Test defaults.
set_defaults("test") {
if (is_android) {
configs = _shared_library_configs
} else {
configs = _executable_configs
}
}
# ==============================================================================
# TOOLCHAIN SETUP
# ==============================================================================
#
# Here we set the default toolchain, as well as the variable host_toolchain
# which will identify the toolchain corresponding to the local system when
# doing cross-compiles. When not cross-compiling, this will be the same as the
# default toolchain.
import("//build/toolchain/custom/custom.gni")
# Define this to allow Fuchsia's fork of harfbuzz to build.
# shlib_toolchain is a Fuchsia-specific symbol and not used by Flutter.
shlib_toolchain = false
if (custom_toolchain != "") {
assert(custom_sysroot != "")
assert(custom_target_triple != "")
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
set_default_toolchain("//build/toolchain/custom")
} else if (is_win) {
assert(is_clang)
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
set_default_toolchain("//build/toolchain/win:clang_$current_cpu")
} else if (is_android) {
if (host_os == "linux") {
# Use clang for the x86/64 Linux host builds.
if (host_cpu == "x86" || host_cpu == "x64") {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
} else {
host_toolchain = "//build/toolchain/linux:$host_cpu"
}
} else if (host_os == "mac") {
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
} else if (host_os == "win") {
assert(is_clang)
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
} else {
assert(false, "Unknown host for android cross compile")
}
if (is_clang) {
set_default_toolchain("//build/toolchain/android:clang_$current_cpu")
} else {
set_default_toolchain("//build/toolchain/android:$current_cpu")
}
} else if (is_linux) {
if (is_clang) {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
set_default_toolchain("//build/toolchain/linux:clang_$current_cpu")
} else {
host_toolchain = "//build/toolchain/linux:$host_cpu"
set_default_toolchain("//build/toolchain/linux:$current_cpu")
}
if (is_chromeos && cros_use_custom_toolchain) {
set_default_toolchain("//build/toolchain/cros:target")
}
} else if (is_mac) {
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
set_default_toolchain("//build/toolchain/mac:clang_$current_cpu")
} else if (is_ios) {
import("//build/config/ios/ios_sdk.gni") # For use_ios_simulator
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
if (use_ios_simulator) {
if (target_cpu == "arm64") {
set_default_toolchain("//build/toolchain/mac:ios_clang_arm_sim")
} else {
set_default_toolchain("//build/toolchain/mac:ios_clang_x64_sim")
}
} else {
set_default_toolchain("//build/toolchain/mac:ios_clang_arm")
}
} else if (is_fuchsia) {
if (host_os == "mac") {
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
} else {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
}
set_default_toolchain("//build/toolchain/fuchsia")
} else if (is_wasm) {
ar = "ar"
cc = "cc"
cxx = "c++"
win_vc = ""
win_toolchain_version = ""
clang_win = ""
clang_win_version = ""
host_toolchain = "//build/toolchain/wasm"
set_default_toolchain("//build/toolchain/wasm")
} else {
assert(false, "Toolchain not set because of unknown platform.")
}
# Sets default dependencies for executable and shared_library targets.
#
# Variables
# no_default_deps: If true, no standard dependencies will be added.
if (use_flutter_cxx) {
foreach(_target_type,
[
"executable",
"loadable_module",
"shared_library",
]) {
template(_target_type) {
target(_target_type, target_name) {
forward_variables_from(invoker, "*", [ "no_default_deps" ])
if (!defined(deps)) {
deps = []
}
if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) {
deps += [ "//flutter/third_party/libcxx" ]
}
}
}
}
}
# ==============================================================================
# COMPONENT SETUP
# ==============================================================================
# TODO(brettw) erase this once the built-in "component" function is removed.
if (is_component_build) {
component_mode = "shared_library"
} else {
component_mode = "source_set"
}
template("component") {
if (is_component_build) {
shared_library(target_name) {
# Configs will always be defined since we set_defaults for a component
# above. We want to use those rather than whatever came with the nested
# shared/static library inside the component.
configs = [] # Prevent list overwriting warning.
configs = invoker.configs
if (defined(invoker.all_dependent_configs)) {
all_dependent_configs = invoker.all_dependent_configs
}
if (defined(invoker.allow_circular_includes_from)) {
allow_circular_includes_from = invoker.allow_circular_includes_from
}
if (defined(invoker.cflags)) {
cflags = invoker.cflags
}
if (defined(invoker.cflags_c)) {
cflags_c = invoker.cflags_c
}
if (defined(invoker.cflags_cc)) {
cflags_cc = invoker.cflags_cc
}
if (defined(invoker.cflags_objc)) {
cflags_objc = invoker.cflags_objc
}
if (defined(invoker.cflags_objcc)) {
cflags_objcc = invoker.cflags_objcc
}
if (defined(invoker.check_includes)) {
check_includes = invoker.check_includes
}
if (defined(invoker.data)) {
data = invoker.data
}
if (defined(invoker.data_deps)) {
data_deps = invoker.data_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
if (defined(invoker.defines)) {
defines = invoker.defines
}
# All shared libraries must have the sanitizer deps to properly link in
# asan mode (this target will be empty in other cases).
if (defined(invoker.deps)) {
deps = invoker.deps + [ "//build/config/sanitizers:deps" ]
} else {
deps = [ "//build/config/sanitizers:deps" ]
}
if (defined(invoker.direct_dependent_configs)) {
direct_dependent_configs = invoker.direct_dependent_configs
}
if (defined(invoker.forward_dependent_configs_from)) {
forward_dependent_configs_from = invoker.forward_dependent_configs_from
}
if (defined(invoker.frameworks)) {
frameworks = invoker.frameworks
}
if (defined(invoker.include_dirs)) {
include_dirs = invoker.include_dirs
}
if (defined(invoker.ldflags)) {
ldflags = invoker.ldflags
}
if (defined(invoker.lib_dirs)) {
lib_dirs = invoker.lib_dirs
}
if (defined(invoker.libs)) {
libs = invoker.libs
}
if (defined(invoker.output_extension)) {
output_extension = invoker.output_extension
}
if (defined(invoker.output_name)) {
output_name = invoker.output_name
}
if (defined(invoker.public)) {
public = invoker.public
}
if (defined(invoker.public_configs)) {
public_configs = invoker.public_configs
}
if (defined(invoker.public_deps)) {
public_deps = invoker.public_deps
}
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
}
} else {
source_set(target_name) {
# See above.
configs = [] # Prevent list overwriting warning.
configs = invoker.configs
if (defined(invoker.all_dependent_configs)) {
all_dependent_configs = invoker.all_dependent_configs
}
if (defined(invoker.allow_circular_includes_from)) {
allow_circular_includes_from = invoker.allow_circular_includes_from
}
if (defined(invoker.cflags)) {
cflags = invoker.cflags
}
if (defined(invoker.cflags_c)) {
cflags_c = invoker.cflags_c
}
if (defined(invoker.cflags_cc)) {
cflags_cc = invoker.cflags_cc
}
if (defined(invoker.cflags_objc)) {
cflags_objc = invoker.cflags_objc
}
if (defined(invoker.cflags_objcc)) {
cflags_objcc = invoker.cflags_objcc
}
if (defined(invoker.check_includes)) {
check_includes = invoker.check_includes
}
if (defined(invoker.data)) {
data = invoker.data
}
if (defined(invoker.data_deps)) {
data_deps = invoker.data_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
if (defined(invoker.defines)) {
defines = invoker.defines
}
if (defined(invoker.deps)) {
deps = invoker.deps
}
if (defined(invoker.direct_dependent_configs)) {
direct_dependent_configs = invoker.direct_dependent_configs
}
if (defined(invoker.forward_dependent_configs_from)) {
forward_dependent_configs_from = invoker.forward_dependent_configs_from
}
if (defined(invoker.frameworks)) {
frameworks = invoker.frameworks
}
if (defined(invoker.include_dirs)) {
include_dirs = invoker.include_dirs
}
if (defined(invoker.ldflags)) {
ldflags = invoker.ldflags
}
if (defined(invoker.lib_dirs)) {
lib_dirs = invoker.lib_dirs
}
if (defined(invoker.libs)) {
libs = invoker.libs
}
if (defined(invoker.output_extension)) {
output_extension = invoker.output_extension
}
if (defined(invoker.output_name)) {
output_name = invoker.output_name
}
if (defined(invoker.public)) {
public = invoker.public
}
if (defined(invoker.public_configs)) {
public_configs = invoker.public_configs
}
if (defined(invoker.public_deps)) {
public_deps = invoker.public_deps
}
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
}
}
}

View File

@@ -0,0 +1,8 @@
# 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.
declare_args() {
# Memory allocator to use. Set to "none" to use default allocator.
use_allocator = "none"
}

View File

@@ -0,0 +1,24 @@
# 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/config/android/config.gni")
import("//build/config/sysroot.gni")
config("sdk") {
if (sysroot != "") {
cflags = [ "--sysroot=" + sysroot ]
ldflags = [ "-L" + rebase_path("$android_lib", root_build_dir) ]
}
}
config("executable_config") {
cflags = [ "-fPIE" ]
ldflags = [ "-pie" ]
}
config("hide_all_but_jni_onload") {
ldflags = [ "-Wl,--version-script=" + rebase_path(
"//build/android/android_only_explicit_jni_exports.lst",
root_build_dir) ]
}

View File

@@ -0,0 +1,111 @@
# 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.
# This file contains common system config stuff for the Android build.
if (is_android) {
if (!defined(default_android_sdk_root)) {
default_android_sdk_root = "//flutter/third_party/android_tools/sdk"
default_android_sdk_version = "35"
default_android_sdk_build_tools_version = "35.0.0-rc4"
}
declare_args() {
android_sdk_root = default_android_sdk_root
android_sdk_version = default_android_sdk_version
android_sdk_build_tools_version = default_android_sdk_build_tools_version
# Unused. Required for GN files maintained in other buildroots.
enable_java_templates = false
android_api_level = 22
}
# Host stuff -----------------------------------------------------------------
# Defines the name the Android build gives to the current host CPU
# architecture, which is different than the names GN uses.
if (host_cpu == "x64" || host_cpu == "x86" || host_cpu == "arm64") {
android_host_arch = "x86_64"
} else {
assert(false, "Need Android toolchain support for your build CPU arch.")
}
# Defines the name the Android build gives to the current host CPU
# architecture, which is different than the names GN uses.
if (host_os == "linux") {
android_host_os = "linux"
} else if (host_os == "mac") {
android_host_os = "darwin"
} else if (host_os == "win") {
android_host_os = "win"
} else {
assert(false, "Need Android toolchain support for your build OS.")
}
# Directories and files ------------------------------------------------------
#
# We define may of the dirs strings here for each output architecture (rather
# than just the current one) since these are needed by the Android toolchain
# file to define toolchains for all possible targets in one pass.
android_sdk = "${android_sdk_root}/platforms/android-${android_sdk_version}"
# Path to the Android NDK and SDK.
android_ndk_root = "//flutter/third_party/android_tools/ndk"
android_ndk_include_dir = "$android_ndk_root/usr/include"
android_sdk = "${android_sdk_root}/platforms/android-${android_sdk_version}"
android_sdk_tools = "${android_sdk_root}/tools"
android_sdk_build_tools =
"${android_sdk_root}/build-tools/$android_sdk_build_tools_version"
# Path to the SDK's android.jar
android_sdk_jar = "$android_sdk/android.jar"
zipalign_path = "$android_sdk_build_tools/zipalign"
if (current_cpu != "x64" && current_cpu != "arm64") {
android_api_level = 21
}
# Toolchain root directory for each build. The actual binaries are inside
# a "bin" directory inside of these.
llvm_android_toolchain_root = "$android_ndk_root/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}"
android_toolchain_root = "$android_ndk_root/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}"
# Toolchain stuff ------------------------------------------------------------
_android_lib_prefix = "$android_toolchain_root/sysroot/usr/lib"
if (component_mode == "shared_library") {
# By appending .cr, we prevent name collisions with libraries already
# loaded by the Android zygote.
android_product_extension = ".cr.so"
} else {
android_product_extension = ".so"
}
# ABI ------------------------------------------------------------------------
if (current_cpu == "x86") {
android_app_abi = "x86"
_android_lib_dir = "i686-linux-android"
} else if (current_cpu == "arm") {
android_app_abi = "armeabi-v7a"
_android_lib_dir = "arm-linux-androideabi"
} else if (current_cpu == "x64") {
android_app_abi = "x86_64"
_android_lib_dir = "x86_64-linux-android"
} else if (current_cpu == "arm64") {
android_app_abi = "arm64-v8a"
_android_lib_dir = "aarch64-linux-android"
} else {
assert(false, "Unknown Android ABI: " + current_cpu)
}
android_lib = "$_android_lib_prefix/$_android_lib_dir/$android_api_level"
android_log_tag = "\"flutter\""
}

View File

@@ -0,0 +1,7 @@
# 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.
# TODO(dnfield): Patch icu to not depend on this file
import("//build/config/android/config.gni")
assert(is_android)

View File

@@ -0,0 +1,68 @@
# 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.
if (current_cpu == "arm" || current_cpu == "arm64") {
declare_args() {
# Version of the ARM processor when compiling on ARM. Ignored on non-ARM
# platforms.
if (current_cpu == "arm") {
arm_version = 7
} else if (current_cpu == "arm64") {
arm_version = 8
} else {
assert(false, "Unconfigured arm version")
}
# The ARM floating point mode. This is either the string "hard", "soft", or
# "softfp". An empty string means to use the default one for the
# arm_version.
arm_float_abi = ""
# The ARM variant-specific tuning mode. This will be a string like "armv6"
# or "cortex-a15". An empty string means to use the default for the
# arm_version.
arm_tune = ""
# Whether to use the neon FPU instruction set or not.
arm_use_neon = true
# Whether to enable optional NEON code paths.
arm_optionally_use_neon = false
}
assert(arm_float_abi == "" || arm_float_abi == "hard" ||
arm_float_abi == "soft" || arm_float_abi == "softfp")
if (arm_version == 6) {
arm_arch = "armv6"
if (arm_tune != "") {
arm_tune = ""
}
if (arm_float_abi == "") {
arm_float_abi = "softfp"
}
arm_fpu = "vfp"
# Thumb is a reduced instruction set available on some ARM processors that
# has increased code density.
arm_use_thumb = false
} else if (arm_version == 7) {
arm_arch = "armv7-a"
if (arm_tune == "") {
arm_tune = "generic-armv7-a"
}
if (arm_float_abi == "") {
arm_float_abi = "softfp"
}
arm_use_thumb = true
if (arm_use_neon) {
arm_fpu = "neon"
} else {
arm_fpu = "vfpv3-d16"
}
}
}

View File

@@ -0,0 +1,9 @@
# Copyright 2015 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.
declare_args() {
# Use libc++ (buildtools/third_party/libc++ and
# buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
use_custom_libcxx = false
}

View File

@@ -0,0 +1,36 @@
# Copyright (c) 2013 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/toolchain/clang.gni")
import("//build/toolchain/toolchain.gni")
import("clang.gni")
# Empty entry to satisfy ANGLE build, which tries to remove this config.
config("find_bad_constructs") {
}
# 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 = [
# Warns when a const char[] is converted to bool.
"-Wstring-conversion",
# Warns when a source file doesn't have a newline at end-of-file.
# This is to match Fuchsia, which enables this warning.
"-Wnewline-eof",
]
defines = [ "_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS" ]
}
group("llvm-symbolizer_data") {
if (is_win) {
data = [ "$buildtools_path/windows-x64/bin/llvm-symbolizer.exe" ]
} else if (is_mac) {
data = [ "$buildtools_path/mac-${host_cpu}/clang/bin/llvm-symbolizer" ]
} else if (is_linux) {
data = [ "$buildtools_path/linux-${host_cpu}/clang/bin/llvm-symbolizer" ]
}
}

View File

@@ -0,0 +1,6 @@
# 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.
declare_args() {
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
# Copyright 2013 The Flutter 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 is a subset of Chromium's build/config/compiler/compiler.gni
# required for compatibility with Chromium packages such as zlib.
declare_args() {
build_with_chromium = false
use_libfuzzer = false
is_apple = is_ios || is_mac
use_thin_lto = false
# zlib uses this identifier
use_fuzzing_engine = false
}

View File

@@ -0,0 +1,29 @@
# Copyright (c) 2013 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 declares build flags for the SSL library configuration.
#
# TODO(brettw) this should probably be moved to src/crypto or somewhere, and
# the global build dependency on it should be removed.
#
# PLEASE TRY TO AVOID ADDING FLAGS TO THIS FILE in cases where grit isn't
# required. See the declare_args block of BUILDCONFIG.gn for advice on how
# to set up feature flags.
declare_args() {
# Use OpenSSL instead of NSS. This is used for all platforms but iOS. (See
# http://crbug.com/338886).
use_openssl = !is_ios
}
# True when we're using OpenSSL for representing certificates. When targeting
# Android, the platform certificate library is used for certificate
# verification. On other targets, this flag also enables OpenSSL for certificate
# verification, but this configuration is unsupported.
use_openssl_certs = is_android
# True if NSS is used for certificate verification. Note that this is
# independent from use_openssl. It is possible to use OpenSSL for the crypto
# library, but NSS for the platform certificate library.
use_nss_certs = false

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2016 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.
# Needed for ANGLE build.
dcheck_is_configurable = false
declare_args() {
# Set to true to enable dcheck in Release builds.
dcheck_always_on = false
}

View File

@@ -0,0 +1,23 @@
# 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.
# This file contains Chrome-feature-related build flags (see ui.gni for
# UI-related ones). These should theoretically be moved to the build files of
# the features themselves.
#
# However, today we have many "bad" dependencies on some of these flags from,
# e.g. base, so they need to be global to match the GYP configuration. Also,
# anything that needs a grit define must be in either this file or ui.gni.
#
# PLEASE TRY TO AVOID ADDING FLAGS TO THIS FILE in cases where grit isn't
# required. See the declare_args block of BUILDCONFIG.gn for advice on how
# to set up feature flags.
if (is_android) {
import("//build/config/android/config.gni")
}
declare_args() {
use_blink = false
}

View File

@@ -0,0 +1,95 @@
# 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/config/profiler.gni")
import("//build/toolchain/rbe.gni")
# This config causes functions not to be automatically exported from shared
# libraries. By default, all symbols are exported but this means there are
# lots of exports that slow everything down. In general we explicitly mark
# which functiosn we want to export from components.
#
# Some third_party code assumes all functions are exported so this is separated
# into its own config so such libraries can remove this config to make symbols
# public again.
#
# See http://gcc.gnu.org/wiki/Visibility
config("symbol_visibility_hidden") {
# Note that -fvisibility-inlines-hidden is set globally in the compiler
# config since that can almost always be applied.
if (!enable_profiling && !disable_hidden_visibility) {
defines = [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ]
cflags = [ "-fvisibility=hidden" ]
}
}
# Settings for executables and shared libraries.
config("executable_ldconfig") {
if (is_android) {
ldflags = [
"-Bdynamic",
"-Wl,-z,nocopyreloc",
]
} else {
# Android doesn't support rpath.
ldflags = [
# Want to pass "\$". GN will re-escape as required for ninja.
"-Wl,-rpath=\$ORIGIN/",
"-Wl,-rpath-link=",
# Newer binutils don't set DT_RPATH unless you disable "new" dtags
# and the new DT_RUNPATH doesn't work without --no-as-needed flag.
"-Wl,--disable-new-dtags",
]
}
}
config("no_exceptions") {
no_exceptions_flags = [ "-fno-exceptions" ]
cflags_cc = no_exceptions_flags
cflags_objcc = no_exceptions_flags
}
config("relative_paths") {
# Make builds independent of absolute file path. The file names
# embedded in debugging information will be expressed as relative to
# the build directory, e.g. "../.." for an "out/subdir" under //.
# This is consistent with the file names in __FILE__ expansions
# (e.g. in assertion messages), which the compiler doesn't provide a
# way to remap. That way source file names in logging and
# symbolization can all be treated the same way. This won't go well
# if root_build_dir is not a subdirectory //, but there isn't a better
# option to keep all source file name references uniformly relative to
# a single root.
cflags = []
cflags_objcc = []
absolute_path = rebase_path("//")
relative_path = ""
if (use_rbe) {
# objc builds are always local even when rbe is enabled.
cflags_objcc += [
# This makes sure that the DW_AT_comp_dir string (the current
# directory while running the compiler, which is the basis for all
# relative source file names in the DWARF info) is represented as
# relative to //.
"-fdebug-prefix-map=$absolute_path=$relative_path",
]
} else {
cflags += [
"-fdebug-prefix-map=$absolute_path=$relative_path",
]
}
cflags += [
# This makes sure that include directories in the toolchain are
# represented as relative to the build directory (because that's how
# we invoke the compiler), rather than absolute. This can affect
# __FILE__ expansions (e.g. assertions in system headers). We
# normally run a compiler that's someplace within the source tree
# (//buildtools/...), so its absolute installation path will have a
# prefix matching absolute_path and hence be mapped to relative_path
# in the debugging information, so this should actually be
# superfluous for purposes of the debugging information.
"-no-canonical-prefixes",
]
}

View File

@@ -0,0 +1,25 @@
# 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.
if (is_android) {
gcc_version = 49
} else if (current_toolchain == "//build/toolchain/cros:target") {
gcc_version = exec_script("../../compiler_version.py",
[
"target",
"compiler",
],
"value")
} else if (current_toolchain == "//build/toolchain/linux:x64" ||
current_toolchain == "//build/toolchain/linux:x86") {
# These are both the same and just use the default gcc on the system.
gcc_version = exec_script("../../compiler_version.py",
[
"host",
"compiler",
],
"value")
} else {
gcc_version = 0
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2017 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 header file defines the "host_byteorder" variable.
# Not that this is currently used only for building v8.
# The chromium code generally assumes little-endianness.
declare_args() {
host_byteorder = "undefined"
}
# Detect host byteorder
# ppc64 can be either BE or LE
if (host_cpu == "ppc64") {
if (current_os == "aix") {
host_byteorder = "big"
} else {
# Only use the script when absolutely necessary
host_byteorder =
exec_script("//build/config/get_host_byteorder.py", [], "trim string")
}
} else if (host_cpu == "ppc" || host_cpu == "s390" || host_cpu == "s390x") {
host_byteorder = "big"
} else {
host_byteorder = "little"
}

View File

@@ -0,0 +1,7 @@
# 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.
config("sdk") {
cflags_cc = [ "-stdlib=libc++" ]
}

View File

@@ -0,0 +1,68 @@
# Copyright 2015 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/toolchain/rbe.gni")
declare_args() {
# SDK path to use. When empty this will use the default SDK based on the
# value of use_ios_simulator.
ios_sdk_path = ""
# Set to true when targeting a simulator build on iOS. False means that the
# target is for running on the device. The default value is to use the
# Simulator except when targeting GYP's Xcode builds (for compat with the
# existing GYP build).
use_ios_simulator = true
# Alias for use_ios_simulator used by Skia.
ios_use_simulator = true
# Version of iOS that we're targeting.
ios_deployment_target = "12.0"
# The path to the iOS device SDK.
ios_device_sdk_path = ""
# The path to the iOS simulator SDK.
ios_simulator_sdk_path = ""
# Version of iOS that we're targeting for tests.
ios_testing_deployment_target = "13.0"
}
if (ios_sdk_path == "") {
ios_sdk_args = []
if (use_rbe && create_xcode_symlinks) {
ios_sdk_args += [
"--symlink",
rebase_path("//flutter/prebuilts"),
]
}
if (!use_ios_simulator && ios_device_sdk_path == "") {
ios_sdk_args += [
"--sdk",
"iphoneos",
]
_ios_device_sdk_result =
exec_script("ios_sdk.py", ios_sdk_args, "list lines")
ios_device_sdk_path = _ios_device_sdk_result[0]
}
if (use_ios_simulator && ios_simulator_sdk_path == "") {
ios_sdk_args += [
"--sdk",
"iphonesimulator",
]
_ios_sim_sdk_result = exec_script("ios_sdk.py", ios_sdk_args, "list lines")
ios_simulator_sdk_path = _ios_sim_sdk_result[0]
}
if (use_ios_simulator) {
assert(ios_simulator_sdk_path != "")
ios_sdk_path = ios_simulator_sdk_path
} else {
assert(ios_device_sdk_path != "")
ios_sdk_path = ios_device_sdk_path
}
}

View File

@@ -0,0 +1,117 @@
# 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 argparse
import errno
import os
import shutil
import subprocess
import sys
sys.path.insert(1, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
from pyutil.file_util import symlink
# This script creates symlinks under flutter/prebuilts to the iphone and
# iphone simulator SDKs.
SDKs = ['iphoneos', 'iphonesimulator']
PREBUILTS = os.path.realpath(os.path.join(
os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, 'flutter', 'prebuilts',
))
def run_command_with_retry(command, timeout=10, retries=3):
"""
Runs a command using subprocess.check_output with timeout and retry logic.
Args:
command: A list representing the command and its arguments.
timeout: The maximum time (in seconds) to wait for each command execution.
retries: The number of times to retry the command if it times out.
Returns:
The output of the command as a bytes object if successful, otherwise
raises a CalledProcessError.
"""
for attempt in range(1, retries + 1):
try:
result = subprocess.check_output(command, timeout=timeout)
return result.decode('utf-8').strip()
except subprocess.TimeoutExpired:
if attempt >= retries:
raise # Re-raise the TimeoutExpired error after all retries
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
'--as-gclient-hook',
default=False,
action='store_true',
help='Whether the script is running as a gclient hook.',
)
parser.add_argument(
'--symlink',
type=str,
help='Whether to create a symlink in the buildroot to the SDK.',
)
parser.add_argument(
'--sdk',
choices=['iphoneos', 'iphonesimulator'],
help='Which SDK to find.',
)
args = parser.parse_args()
# On CI, Xcode is not yet installed when gclient hooks are being run.
# This is because the version of Xcode that CI installs might depend on the
# contents of the repo, so the repo must be set up first, which includes
# running the gclient hooks. Instead, on CI, this script will be run during
# GN.
running_on_luci = os.environ.get('LUCI_CONTEXT') is not None
if running_on_luci and args.as_gclient_hook:
return 0
symlink_path = args.symlink
if not running_on_luci and symlink_path is None:
symlink_path = PREBUILTS
sdks = [args.sdk] if args.sdk is not None else SDKs
sdks_path = None
libraries_path = None
if symlink_path:
sdks_path = os.path.join(symlink_path, 'SDKs')
libraries_path = os.path.join(symlink_path, 'Library')
# Remove any old files created by this script under PREBUILTS/SDKs.
if args.as_gclient_hook:
if os.path.isdir(sdks_path):
shutil.rmtree(sdks_path)
if os.path.isdir(libraries_path):
shutil.rmtree(libraries_path)
for sdk in sdks:
command = [
'xcrun',
'--sdk',
sdk,
'--show-sdk-path',
]
sdk_output = run_command_with_retry(command, timeout=300)
if symlink_path:
symlink_target = os.path.join(sdks_path, os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
frameworks_location = os.path.join(sdk_output, '..', '..', 'Library', 'Frameworks')
frameworks_symlink = os.path.join(libraries_path, 'Frameworks')
symlink(frameworks_location, frameworks_symlink)
sdk_output = symlink_target
if not args.as_gclient_hook:
print(sdk_output)
return 0
if __name__ == '__main__':
if sys.platform != 'darwin':
raise Exception('This script only runs on Mac')
sys.exit(main(sys.argv))

View File

@@ -0,0 +1,62 @@
# Copyright (c) 2013 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/features.gni")
import("//build/config/linux/pkg_config.gni")
import("//build/config/sysroot.gni")
import("//build/config/ui.gni")
config("sdk") {
if (sysroot != "") {
cflags = [ "--sysroot=" + sysroot ]
ldflags = [ "--sysroot=" + sysroot ]
# Need to get some linker flags out of the sysroot.
ldflags += [ exec_script("sysroot_ld_path.py",
[
rebase_path("//build/linux/sysroot_ld_path.sh",
root_build_dir),
sysroot,
],
"value") ]
}
}
config("fontconfig") {
libs = [ "fontconfig" ]
}
pkg_config("freetype2") {
packages = [ "freetype2" ]
}
config("x11") {
libs = [
"X11",
"Xcomposite",
"Xcursor",
"Xdamage",
"Xext",
"Xfixes",
"Xi",
"Xrender",
"Xtst",
]
}
config("xrandr") {
libs = [ "Xrandr" ]
}
config("xinerama") {
libs = [ "Xinerama" ]
}
config("xcomposite") {
libs = [ "Xcomposite" ]
}
config("xext") {
libs = [ "Xext" ]
}

View File

@@ -0,0 +1,249 @@
#!/usr/bin/env python3
#
# Copyright (c) 2013 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 json
import os
import subprocess
import sys
import re
from optparse import OptionParser
# This script runs pkg-config, optionally filtering out some results, and
# returns the result.
#
# The result will be [ <includes>, <cflags>, <libs>, <lib_dirs>, <ldflags> ]
# where each member is itself a list of strings.
#
# You can filter out matches using "-v <regexp>" where all results from
# pkgconfig matching the given regular expression will be ignored. You can
# specify more than one regular expression my specifying "-v" more than once.
#
# You can specify a sysroot using "-s <sysroot>" where sysroot is the absolute
# system path to the sysroot used for compiling. This script will attempt to
# generate correct paths for the sysroot.
#
# When using a sysroot, you must also specify the architecture via
# "-a <arch>" where arch is either "x86" or "x64".
#
# CrOS systemroots place pkgconfig files at <systemroot>/usr/share/pkgconfig
# and one of <systemroot>/usr/lib/pkgconfig or <systemroot>/usr/lib64/pkgconfig
# depending on whether the systemroot is for a 32 or 64 bit architecture. They
# specify the 'lib' or 'lib64' of the pkgconfig path by defining the
# 'system_libdir' variable in the args.gn file. pkg_config.gni communicates this
# variable to this script with the "--system_libdir <system_libdir>" flag. If no
# flag is provided, then pkgconfig files are assumed to come from
# <systemroot>/usr/lib/pkgconfig.
#
# Additionally, you can specify the option --atleast-version. This will skip
# the normal outputting of a dictionary and instead print true or false,
# depending on the return value of pkg-config for the given package.
def SetConfigPath(options):
"""Set the PKG_CONFIG_LIBDIR environment variable.
This takes into account any sysroot and architecture specification from the
options on the given command line.
"""
sysroot = options.sysroot
assert sysroot
# Compute the library path name based on the architecture.
arch = options.arch
if sysroot and not arch:
print("You must specify an architecture via -a if using a sysroot.")
sys.exit(1)
libdir = sysroot + '/usr/' + options.system_libdir + '/pkgconfig'
libdir += ':' + sysroot + '/usr/share/pkgconfig'
os.environ['PKG_CONFIG_LIBDIR'] = libdir
return libdir
def GetPkgConfigPrefixToStrip(options, args):
"""Returns the prefix from pkg-config where packages are installed.
This returned prefix is the one that should be stripped from the beginning of
directory names to take into account sysroots.
"""
# Some sysroots, like the Chromium OS ones, may generate paths that are not
# relative to the sysroot. For example,
# /path/to/chroot/build/x86-generic/usr/lib/pkgconfig/pkg.pc may have all
# paths relative to /path/to/chroot (i.e. prefix=/build/x86-generic/usr)
# instead of relative to /path/to/chroot/build/x86-generic (i.e prefix=/usr).
# To support this correctly, it's necessary to extract the prefix to strip
# from pkg-config's |prefix| variable.
prefix = subprocess.check_output([options.pkg_config,
"--variable=prefix"] + args, env=os.environ).decode('utf-8')
if prefix[-4] == '/usr':
return prefix[4:]
return prefix
def MatchesAnyRegexp(flag, list_of_regexps):
"""Returns true if the first argument matches any regular expression in the
given list."""
for regexp in list_of_regexps:
if regexp.search(flag) != None:
return True
return False
def RewritePath(path, strip_prefix, sysroot):
"""Rewrites a path by stripping the prefix and prepending the sysroot."""
if os.path.isabs(path) and not path.startswith(sysroot):
if path.startswith(strip_prefix):
path = path[len(strip_prefix):]
path = path.lstrip('/')
return os.path.join(sysroot, path)
else:
return path
def main():
# If this is run on non-Linux platforms, just return nothing and indicate
# success. This allows us to "kind of emulate" a Linux build from other
# platforms.
if "linux" not in sys.platform:
print("[[],[],[],[],[]]")
return 0
parser = OptionParser()
parser.add_option('-d', '--debug', action='store_true')
parser.add_option('-p', action='store', dest='pkg_config', type='string',
default='pkg-config')
parser.add_option('-v', action='append', dest='strip_out', type='string')
parser.add_option('-s', action='store', dest='sysroot', type='string')
parser.add_option('-a', action='store', dest='arch', type='string')
parser.add_option('--system_libdir', action='store', dest='system_libdir',
type='string', default='lib')
parser.add_option('--atleast-version', action='store',
dest='atleast_version', type='string')
parser.add_option('--libdir', action='store_true', dest='libdir')
parser.add_option('--dridriverdir', action='store_true', dest='dridriverdir')
parser.add_option('--version-as-components', action='store_true',
dest='version_as_components')
(options, args) = parser.parse_args()
# Make a list of regular expressions to strip out.
strip_out = []
if options.strip_out != None:
for regexp in options.strip_out:
strip_out.append(re.compile(regexp))
if options.sysroot:
libdir = SetConfigPath(options)
if options.debug:
sys.stderr.write('PKG_CONFIG_LIBDIR=%s\n' % libdir)
prefix = GetPkgConfigPrefixToStrip(options, args)
else:
prefix = ''
if options.atleast_version:
# When asking for the return value, just run pkg-config and print the return
# value, no need to do other work.
if not subprocess.call([options.pkg_config,
"--atleast-version=" + options.atleast_version] +
args):
print("true")
else:
print("false")
return 0
if options.version_as_components:
cmd = [options.pkg_config, "--modversion"] + args
try:
version_string = subprocess.check_output(cmd).decode('utf-8')
except:
sys.stderr.write('Error from pkg-config.\n')
return 1
print(json.dumps(list(map(int, version_string.strip().split(".")))))
return 0
if options.libdir:
cmd = [options.pkg_config, "--variable=libdir"] + args
if options.debug:
sys.stderr.write('Running: %s\n' % cmd)
try:
libdir = subprocess.check_output(cmd).decode('utf-8')
except:
print("Error from pkg-config.")
return 1
sys.stdout.write(libdir.strip())
return 0
if options.dridriverdir:
cmd = [options.pkg_config, "--variable=dridriverdir"] + args
if options.debug:
sys.stderr.write('Running: %s\n' % cmd)
try:
dridriverdir = subprocess.check_output(cmd).decode('utf-8')
except:
print("Error from pkg-config.")
return 1
sys.stdout.write(dridriverdir.strip())
return
cmd = [options.pkg_config, "--cflags", "--libs"] + args
if options.debug:
sys.stderr.write('Running: %s\n' % ' '.join(cmd))
try:
flag_string = subprocess.check_output(cmd).decode('utf-8')
except:
sys.stderr.write('Could not run pkg-config.\n')
return 1
# For now just split on spaces to get the args out. This will break if
# pkgconfig returns quoted things with spaces in them, but that doesn't seem
# to happen in practice.
all_flags = flag_string.strip().split(' ')
sysroot = options.sysroot
if not sysroot:
sysroot = ''
includes = []
cflags = []
libs = []
lib_dirs = []
for flag in all_flags[:]:
if len(flag) == 0 or MatchesAnyRegexp(flag, strip_out):
continue;
if flag[:2] == '-l':
libs.append(RewritePath(flag[2:], prefix, sysroot))
elif flag[:2] == '-L':
lib_dirs.append(RewritePath(flag[2:], prefix, sysroot))
elif flag[:2] == '-I':
includes.append(RewritePath(flag[2:], prefix, sysroot))
elif flag[:3] == '-Wl':
# Don't allow libraries to control ld flags. These should be specified
# only in build files.
pass
elif flag == '-pthread':
# Many libs specify "-pthread" which we don't need since we always include
# this anyway. Removing it here prevents a bunch of duplicate inclusions
# on the command line.
pass
else:
cflags.append(flag)
# Output a GN array, the first one is the cflags, the second are the libs. The
# JSON formatter prints GN compatible lists when everything is a list of
# strings.
print(json.dumps([includes, cflags, libs, lib_dirs]))
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,128 @@
# Copyright (c) 2013 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/sysroot.gni")
# Defines a config specifying the result of running pkg-config for the given
# packages. Put the package names you want to query in the "packages" variable
# inside the template invocation.
#
# You can also add defines via the "defines" variable. This can be useful to
# add this to the config to pass defines that the library expects to get by
# users of its headers.
#
# Example:
# pkg_config("mything") {
# packages = [ "mything1", "mything2" ]
# defines = [ "ENABLE_AWESOME" ]
# }
#
# You can also use "extra args" to filter out results (see pkg-config.py):
# extra_args = [ "-v, "foo" ]
# To ignore libs and ldflags (only cflags/defines will be set, which is useful
# when doing manual dynamic linking), set:
# ignore_libs = true
declare_args() {
# A pkg-config wrapper to call instead of trying to find and call the right
# pkg-config directly. Wrappers like this are common in cross-compilation
# environments.
# Leaving it blank defaults to searching PATH for 'pkg-config' and relying on
# the sysroot mechanism to find the right .pc files.
pkg_config = ""
# A optional pkg-config wrapper to use for tools built on the host.
host_pkg_config = ""
# CrOS systemroots place pkgconfig files at <systemroot>/usr/share/pkgconfig
# and one of <systemroot>/usr/lib/pkgconfig or <systemroot>/usr/lib64/pkgconfig
# depending on whether the systemroot is for a 32 or 64 bit architecture.
#
# When build under GYP, CrOS board builds specify the 'system_libdir' variable
# as part of the GYP_DEFINES provided by the CrOS emerge build or simple
# chrome build scheme. This variable permits controlling this for GN builds
# in similar fashion by setting the `system_libdir` variable in the build's
# args.gn file to 'lib' or 'lib64' as appropriate for the target architecture.
system_libdir = "lib"
}
pkg_config_script = "//build/config/linux/pkg-config.py"
# Define the args we pass to the pkg-config script for other build files that
# need to invoke it manually.
pkg_config_args = []
if (sysroot != "") {
# Pass the sysroot if we're using one (it requires the CPU arch also).
pkg_config_args += [
"-s",
rebase_path(sysroot, "", root_build_dir),
"-a",
current_cpu,
]
}
if (pkg_config != "") {
pkg_config_args += [
"-p",
pkg_config,
]
}
# Only use the custom libdir when building with the target sysroot.
if (target_sysroot != "" && sysroot == target_sysroot) {
pkg_config_args += [
"--system_libdir",
system_libdir,
]
}
if (host_pkg_config != "") {
host_pkg_config_args = [
"-p",
host_pkg_config,
]
} else {
host_pkg_config_args = pkg_config_args
}
template("pkg_config") {
assert(defined(invoker.packages),
"Variable |packages| must be defined to be a list in pkg_config.")
config(target_name) {
if (host_toolchain == current_toolchain) {
args = host_pkg_config_args + invoker.packages
} else {
args = pkg_config_args + invoker.packages
}
if (defined(invoker.extra_args)) {
args += invoker.extra_args
}
pkgresult = exec_script(pkg_config_script, args, "value")
cflags = pkgresult[1]
foreach(include, pkgresult[0]) {
if (sysroot != "") {
# We want the system include paths to use -isystem instead of -I to
# suppress warnings in those headers.
include_relativized = rebase_path(include, root_build_dir)
cflags += [ "-isystem$include_relativized" ]
} else {
cflags += [ "-I$include" ]
}
}
if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) {
libs = pkgresult[2]
lib_dirs = pkgresult[3]
}
forward_variables_from(invoker,
[
"defines",
"visibility",
])
}
}

View File

@@ -0,0 +1,21 @@
# Copyright (c) 2013 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 takes two arguments, the relative location of the shell script that
# does the checking, and the name of the sysroot.
# TODO(brettw) the build/linux/sysroot_ld_path.sh script should be rewritten in
# Python in this file.
import subprocess
import sys
if len(sys.argv) != 3:
print("Need two arguments")
sys.exit(1)
result = subprocess.check_output([sys.argv[1], sys.argv[2]],
universal_newlines=True).strip()
print('"%s"' % result)

View File

@@ -0,0 +1,118 @@
# 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.
# Note: keep in sync with below.
locales = [
"am",
"ar",
"bg",
"bn",
"ca",
"cs",
"da",
"de",
"el",
"en-GB",
"en-US",
"es-419",
"es",
"et",
"fa",
"fi",
"fil",
"fr",
"gu",
"he",
"hi",
"hr",
"hu",
"id",
"it",
"ja",
"kn",
"ko",
"lt",
"lv",
"ml",
"mr",
"ms",
"nb",
"nl",
"pl",
"pt-BR",
"pt-PT",
"ro",
"ru",
"sk",
"sl",
"sr",
"sv",
"sw",
"ta",
"te",
"th",
"tr",
"uk",
"vi",
"zh-CN",
"zh-TW",
]
# Same as the locales list but in the format Mac expects for output files:
# it uses underscores instead of hyphens, and "en" instead of "en-US".
locales_as_mac_outputs = [
"am",
"ar",
"bg",
"bn",
"ca",
"cs",
"da",
"de",
"el",
"en_GB",
"en",
"es_419",
"es",
"et",
"fa",
"fi",
"fil",
"fr",
"gu",
"he",
"hi",
"hr",
"hu",
"id",
"it",
"ja",
"kn",
"ko",
"lt",
"lv",
"ml",
"mr",
"ms",
"nb",
"nl",
"pl",
"pt_BR",
"pt_PT",
"ro",
"ru",
"sk",
"sl",
"sr",
"sv",
"sw",
"ta",
"te",
"th",
"tr",
"uk",
"vi",
"zh_CN",
"zh_TW",
]

View File

@@ -0,0 +1,30 @@
# Copyright (c) 2013 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/sysroot.gni")
config("sdk") {
cflags_cc = [ "-stdlib=libc++" ]
}
# On Mac, this is used for everything except static libraries.
config("mac_dynamic_flags") {
ldflags = [
"-Wl,-search_paths_first",
"-L.",
# Path for loading shared libraries for unbundled binaries.
"-Wl,-rpath,@loader_path/.",
"-Wl,-rpath,/usr/local/lib/.",
# Path for loading shared libraries for bundled binaries. Get back from
# Binary.app/Contents/MacOS.
"-Wl,-rpath,@loader_path/../../..",
]
}
# On Mac, this is used only for executables.
config("mac_executable_flags") {
ldflags = [ "-Wl,-pie" ] # Position independent.
}

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env python3
#
# Copyright (c) 2015 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
import os
import errno
import subprocess
import sys
PLUTIL = [
'/usr/bin/env',
'xcrun',
'plutil'
]
IBTOOL = [
'/usr/bin/env',
'xcrun',
'ibtool',
]
def MakeDirectories(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
return 0
else:
return -1
return 0
def ProcessInfoPlist(args):
output_plist_file = os.path.abspath(os.path.join(args.output, 'Info.plist'))
return subprocess.check_call( PLUTIL + [
'-convert',
'binary1',
'-o',
output_plist_file,
'--',
args.input,
])
def ProcessNIB(args):
output_nib_file = os.path.join(os.path.abspath(args.output),
"%s.nib" % os.path.splitext(os.path.basename(args.input))[0])
return subprocess.check_call(IBTOOL + [
'--module',
args.module,
'--auto-activate-custom-fonts',
'--target-device',
'mac',
'--compile',
output_nib_file,
os.path.abspath(args.input),
])
def GenerateProjectStructure(args):
application_path = os.path.join( args.dir, args.name + ".app", "Contents" )
return MakeDirectories( application_path )
def Main():
parser = argparse.ArgumentParser(description='A script that aids in '
'the creation of an Mac application')
subparsers = parser.add_subparsers()
# Plist Parser
plist_parser = subparsers.add_parser('plist',
help='Process the Info.plist')
plist_parser.set_defaults(func=ProcessInfoPlist)
plist_parser.add_argument('-i', dest='input', help='The input plist path')
plist_parser.add_argument('-o', dest='output', help='The output plist dir')
# NIB Parser
plist_parser = subparsers.add_parser('nib',
help='Process a NIB file')
plist_parser.set_defaults(func=ProcessNIB)
plist_parser.add_argument('-i', dest='input', help='The input nib path')
plist_parser.add_argument('-o', dest='output', help='The output nib dir')
plist_parser.add_argument('-m', dest='module', help='The module name')
# Directory Structure Parser
dir_struct_parser = subparsers.add_parser('structure',
help='Creates the directory of an Mac application')
dir_struct_parser.set_defaults(func=GenerateProjectStructure)
dir_struct_parser.add_argument('-d', dest='dir', help='Out directory')
dir_struct_parser.add_argument('-n', dest='name', help='App name')
# Engage!
args = parser.parse_args()
return args.func(args)
if __name__ == '__main__':
sys.exit(Main())

View File

@@ -0,0 +1,44 @@
# 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/toolchain/rbe.gni")
declare_args() {
# Minimum supported version of the Mac SDK.
mac_sdk_min = ""
# The MACOSX_DEPLOYMENT_TARGET variable used when compiling.
# Must be of the form x.x.x for Info.plist files.
mac_deployment_target = ""
# Path to a specific version of the Mac SDK, not including a backslash at
# the end. If empty, the path to the lowest version greater than or equal to
# mac_sdk_min is used.
mac_sdk_path = ""
}
assert(mac_sdk_min != "")
assert(mac_deployment_target != "")
if (mac_sdk_path == "") {
find_sdk_args = []
if (use_rbe && create_xcode_symlinks) {
# RBE has a restriction that paths cannot come from outside the build root.
find_sdk_args += [
"--symlink",
rebase_path("//flutter/prebuilts"),
]
}
find_sdk_args += [
"--print_sdk_path",
mac_sdk_min,
]
# The tool will print the SDK path on the first line, and the version on the
# second line.
find_sdk_lines =
exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines")
mac_sdk_path = find_sdk_lines[0]
}

View File

@@ -0,0 +1,60 @@
# Copyright 2016 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
import errno
import os
import shutil
import sys
def Main():
parser = argparse.ArgumentParser(description='Create Mac Framework symlinks')
parser.add_argument('--framework', action='store', type=str, required=True)
parser.add_argument('--version', action='store', type=str)
parser.add_argument('--contents', action='store', type=str, nargs='+')
parser.add_argument('--stamp', action='store', type=str, required=True)
args = parser.parse_args()
VERSIONS = 'Versions'
CURRENT = 'Current'
# Ensure the Foo.framework/Versions/A/ directory exists and create the
# Foo.framework/Versions/Current symlink to it.
if args.version:
try:
os.makedirs(os.path.join(args.framework, VERSIONS, args.version), 744)
except OSError as e:
if e.errno != errno.EEXIST:
raise e
_Relink(os.path.join(args.version),
os.path.join(args.framework, VERSIONS, CURRENT))
# Establish the top-level symlinks in the framework bundle. The dest of
# the symlinks may not exist yet.
if args.contents:
for item in args.contents:
_Relink(os.path.join(VERSIONS, CURRENT, item),
os.path.join(args.framework, item))
# Write out a stamp file.
if args.stamp:
with open(args.stamp, 'w') as f:
f.write(str(args))
return 0
def _Relink(dest, link):
"""Creates a symlink to |dest| named |link|. If |link| already exists,
it is overwritten."""
try:
os.remove(link)
except OSError as e:
if e.errno != errno.ENOENT:
shutil.rmtree(link)
os.symlink(dest, link)
if __name__ == '__main__':
sys.exit(Main())

View File

@@ -0,0 +1,151 @@
# Copyright 2015 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.
mac_app_script = "//build/config/mac/mac_app.py"
template("code_sign_mac") {
assert(defined(invoker.entitlements_path),
"The path to the entitlements .xcent file")
assert(defined(invoker.identity), "The code signing identity")
assert(defined(invoker.application_path), "The application to code sign")
assert(defined(invoker.deps))
action(target_name) {
sources = [ invoker.entitlements_path ]
_application_path = invoker.application_path
script = mac_app_script
outputs = [ "$_application_path/_CodeSignature/CodeResources" ]
args = [
"codesign",
"-p",
rebase_path(invoker.application_path, root_build_dir),
"-i",
invoker.identity,
"-e",
rebase_path(invoker.entitlements_path, root_build_dir),
]
deps = invoker.deps
}
}
template("resource_copy_mac") {
assert(defined(invoker.resources),
"The source list of resources to copy over")
assert(defined(invoker.bundle_directory),
"The directory within the bundle to place the sources in")
assert(defined(invoker.app_name), "The name of the application")
_bundle_directory = invoker.bundle_directory
_app_name = invoker.app_name
_resources = invoker.resources
copy(target_name) {
sources = _resources
outputs = [ "$root_build_dir/$_app_name.app/$_bundle_directory/Contents/Resources/{{source_file_part}}" ]
if (defined(invoker.deps)) {
deps = invoker.deps
}
}
}
template("mac_app") {
assert(defined(invoker.deps),
"Dependencies must be specified for $target_name")
assert(defined(invoker.info_plist),
"The application plist file must be specified for $target_name")
assert(defined(invoker.app_name),
"The name of Mac application for $target_name")
# We just create a variable so we can use the same in interpolation
app_name = invoker.app_name
# Generate the project structure
struct_gen_target_name = target_name + "_struct"
action(struct_gen_target_name) {
script = mac_app_script
sources = []
outputs = [ "$root_build_dir/$app_name.app" ]
args = [
"structure",
"-d",
rebase_path(root_build_dir),
"-n",
app_name,
]
}
# Generate the executable
bin_gen_target_name = target_name + "_bin"
executable(bin_gen_target_name) {
deps = invoker.deps
output_name = app_name
}
# Process the Info.plist
plist_gen_target_name = target_name + "_plist"
action(plist_gen_target_name) {
script = mac_app_script
sources = [ invoker.info_plist ]
outputs = [ "$root_build_dir/plist/$app_name/Info.plist" ]
args = [
"plist",
"-i",
rebase_path(invoker.info_plist, root_build_dir),
"-o",
rebase_path("$root_build_dir/plist/$app_name"),
]
}
# Copy the generated binaries and assets to their appropriate locations
copy_plist_gen_target_name = target_name + "_plist_copy"
copy(copy_plist_gen_target_name) {
sources = [ "$root_build_dir/plist/$app_name/Info.plist" ]
outputs = [ "$root_build_dir/$app_name.app/Contents/{{source_file_part}}" ]
deps = [ ":$plist_gen_target_name" ]
}
copy_bin_target_name = target_name + "_bin_copy"
copy(copy_bin_target_name) {
sources = [ "$root_build_dir/$app_name" ]
outputs =
[ "$root_build_dir/$app_name.app/Contents/MacOS/{{source_file_part}}" ]
deps = [ ":$bin_gen_target_name" ]
}
copy_all_target_name = target_name + "_all_copy"
group(copy_all_target_name) {
deps = [
":$copy_bin_target_name",
":$copy_plist_gen_target_name",
":$struct_gen_target_name",
]
}
# Top level group
group(target_name) {
deps = [ ":$copy_all_target_name" ]
}
}

View File

@@ -0,0 +1,9 @@
# 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.
# This file is required by the ANGLE build.
import("//build/config/ui.gni")
ozone_platform_gbm = false

View File

@@ -0,0 +1,21 @@
# Copyright (c) 2017 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.
declare_args() {
# Compile in such a way as to enable profiling of the generated code. For
# example, don't omit the frame pointer and leave in symbols.
enable_profiling = false
# Use default visibility for all symbols.
# Without this, any symbol that is not specifically exported will have
# hidden visibility.
disable_hidden_visibility = false
# Compile in such a way as to make it possible for the profiler to unwind full
# stack frames. Setting this flag has a large effect on the performance of the
# generated code than just setting profiling, but gives the profiler more
# information to analyze.
# Requires profiling to be set to true.
enable_full_stack_frames_for_profiling = false
}

View File

@@ -0,0 +1,56 @@
# 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/config/c++/c++.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/toolchain/toolchain.gni")
# Contains the dependencies needed for sanitizers to link into executables and
# shared_libraries. Unconditionally depend upon this target as it is empty if
# |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false.
group("deps") {
if (is_asan || is_lsan || is_tsan || is_msan) {
public_configs = [ ":sanitizer_options_link_helper" ]
deps += [ ":options_sources" ]
}
if (use_custom_libcxx) {
deps += [ "$buildtools_path/third_party/libc++:libcxx_proxy" ]
}
}
config("sanitizer_options_link_helper") {
ldflags = [ "-Wl,-u_sanitizer_options_link_helper" ]
if (is_asan) {
ldflags += [ "-fsanitize=address" ]
}
if (is_lsan) {
ldflags += [ "-fsanitize=leak" ]
}
if (is_tsan) {
ldflags += [ "-fsanitize=thread" ]
}
if (is_msan) {
ldflags += [ "-fsanitize=memory" ]
}
}
source_set("options_sources") {
visibility = [
":deps",
"//:gn_visibility",
]
sources = [ "//build/sanitizers/sanitizer_options.cc" ]
if (is_asan) {
sources += [ "//build/sanitizers/asan_suppressions.cc" ]
}
if (is_lsan) {
sources += [ "//build/sanitizers/lsan_suppressions.cc" ]
}
if (is_tsan) {
sources += [ "//build/sanitizers/tsan_suppressions.cc" ]
}
}

View File

@@ -0,0 +1,23 @@
# Copyright 2015 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.
declare_args() {
# Track where uninitialized memory originates from. From fastest to slowest:
# 0 - no tracking, 1 - track only the initial allocation site, 2 - track the
# chain of stores leading from allocation site to use site.
msan_track_origins = 2
# Use dynamic libraries instrumented by one of the sanitizers instead of the
# standard system libraries. Set this flag to download prebuilt binaries from
# GCS.
use_prebuilt_instrumented_libraries = false
is_ubsan_vptr = false
# Perfetto targets fail to build if this argument isn't defined. When true,
# the preprocessor macro ADDRESS_SANITIZER_WITHOUT_INSTRUMENTATION is defined.
use_sanitizer_configs_without_instrumentation = false
}
use_fuzzing_engine = false

View File

@@ -0,0 +1,46 @@
# Copyright (c) 2013 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 header file defines the "sysroot" variable which is the absolute path
# of the sysroot. If no sysroot applies, the variable will be an empty string.
declare_args() {
# The absolute path of the sysroot that is applied when compiling using
# the target toolchain.
target_sysroot = ""
# Whether to use the default sysroot when building for Linux, if an explicit
# sysroot isn't set.
use_default_linux_sysroot = true
}
if (current_toolchain == default_toolchain && target_sysroot != "") {
sysroot = target_sysroot
} else if (is_android) {
import("//build/config/android/config.gni")
sysroot = rebase_path("$android_toolchain_root/sysroot", root_build_dir)
} else if (is_linux && !is_chromeos) {
if (use_default_linux_sysroot && !is_fuchsia) {
if (current_cpu == "x64") {
sysroot =
rebase_path("//build/linux/debian_sid_amd64-sysroot", root_build_dir)
} else {
sysroot =
rebase_path("//build/linux/debian_sid_arm64-sysroot", root_build_dir)
}
assert(
exec_script("//build/dir_exists.py", [ sysroot ], "string") == "True",
"Missing sysroot ($sysroot). To fix, run: build/linux/sysroot_scripts/install-sysroot.py --arch=$current_cpu")
} else {
sysroot = ""
}
} else if (is_mac) {
import("//build/config/mac/mac_sdk.gni")
sysroot = mac_sdk_path
} else if (is_ios) {
import("//build/config/ios/ios_sdk.gni")
sysroot = ios_sdk_path
} else {
sysroot = ""
}

View File

@@ -0,0 +1,55 @@
# Copyright 2015 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.
# Declare a target for processing a template.
#
# Variables
# input: The template file to be processed.
# output: Where to save the result.
# variables: A list of variables to make available to the template
# processing environment, e.g. ["name=foo", "color=red"].
#
# Example
# file_template("chrome_shell_manifest") {
# input = "shell/java/AndroidManifest.xml"
# output = "$target_gen_dir/AndroidManifest.xml"
# variables = "app_name=chrome_shell app_version=1"
# }
template("file_template") {
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
assert(defined(invoker.input), "The input file must be specified")
assert(defined(invoker.output), "The output file must be specified")
assert(defined(invoker.variables),
"The variable used for substitution in templates must be specified")
variables = invoker.variables
action(target_name) {
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
script = "//build/android/gyp/jinja_template.py"
depfile = "$target_gen_dir/$target_name.d"
sources = [ invoker.input ]
outputs = [
invoker.output,
depfile,
]
args = [
"--inputs",
rebase_path(invoker.input, root_build_dir),
"--output",
rebase_path(invoker.output, root_build_dir),
"--depfile",
rebase_path(depfile, root_build_dir),
"--variables=${variables}",
]
}
}

View File

@@ -0,0 +1,26 @@
# 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.
# This file contains UI-related build flags. It should theoretically be in the
# src/ui directory and only things that depend on the ui module should get the
# definitions.
#
# However, today we have many "bad" dependencies on some of these flags from,
# e.g. base, so they need to be global.
#
# See also build/config/features.gni
declare_args() {
# Indicates if GLFW is enabled. GLFW is an abstraction layer for the
# windowing system and OpenGL rendering, providing cross-platform support
# for creating windows and OpenGL surfaces and contexts, and handling
# window system events and input.
use_glfw = false
}
# For ANGLE build. It's a build option there, but hard-coded here.
use_x11 = false
# For ANGLE build. It's a build option there, but hard-coded here.
use_ozone = false

View File

@@ -0,0 +1,198 @@
# Copyright (c) 2013 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/win/visual_studio_version.gni")
# Compiler setup for the Windows SDK. Applied to all targets.
config("sdk") {
# The include path is the stuff returned by the script.
#include_dirs = msvc_config[0] TODO(brettw) make this work.
defines = [
"_ATL_NO_OPENGL",
"_WINDOWS",
"CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
"NTDDI_VERSION=0x06030000",
"PSAPI_VERSION=1",
"WIN32",
"_SECURE_ATL",
# This is required for ATL to use XP-safe versions of its functions.
"_USING_V110_SDK71_",
]
if (target_os == "winuwp") {
defines += [ "WINUWP" ]
}
}
# Sets the default Windows build version. This is separated because some
# targets need to manually override it for their compiles.
config("winver") {
defines = [
"_WIN32_WINNT=0x0603",
"WINVER=0x0603",
]
}
# Linker flags for Windows SDK setup, this is applied only to EXEs and DLLs.
config("sdk_link") {
if (current_cpu == "x64") {
ldflags = [ "/MACHINE:X64" ]
lib_dirs = [
"$windows_sdk_path\Lib\winv6.3\um\x64",
"$visual_studio_path\VC\lib\amd64",
"$visual_studio_path\VC\atlmfc\lib\amd64",
]
} else if (current_cpu == "x86") {
ldflags = [
"/MACHINE:X86",
"/SAFESEH", # Not compatible with x64 so use only for x86.
]
lib_dirs = [
"$windows_sdk_path\Lib\winv6.3\um\x86",
"$visual_studio_path\VC\lib",
"$visual_studio_path\VC\atlmfc\lib",
]
if (!is_asan) {
ldflags += [ "/largeaddressaware" ]
}
} else if (current_cpu == "arm64") {
ldflags = [ "/MACHINE:ARM64" ]
lib_dirs = [
"$windows_sdk_path\Lib\winv6.3\um\arm64",
"$visual_studio_path\VC\lib\arm64",
"$visual_studio_path\VC\atlmfc\lib\arm64",
]
} else {
assert(false, "Unsupported CPU type")
}
}
# This default linker setup is provided separately from the SDK setup so
# targets who want different library configurations can remove this and specify
# their own.
config("common_linker_setup") {
ldflags = [
"/FIXED:NO",
"/ignore:4199",
"/ignore:4221",
"/NXCOMPAT",
# Suggested by Microsoft Devrel to avoid
# LINK : fatal error LNK1248: image size (80000000)
# exceeds maximum allowable size (80000000)
# which started happening more regularly after VS2013 Update 4.
"/maxilksize:2147483647",
]
# ASLR makes debugging with windbg difficult because Chrome.exe and
# Chrome.dll share the same base name. As result, windbg will name the
# Chrome.dll module like chrome_<base address>, where <base address>
# typically changes with each launch. This in turn means that breakpoints in
# Chrome.dll don't stick from one launch to the next. For this reason, we
# turn ASLR off in debug builds.
# /DYNAMICBASE:NO isn't compatible with arm64.
if (is_debug && current_cpu != "arm64") {
ldflags += [ "/DYNAMICBASE:NO" ]
} else {
ldflags += [ "/DYNAMICBASE" ]
}
# Delay loaded DLLs.
ldflags += [
"/DELAYLOAD:dbghelp.dll",
"/DELAYLOAD:dwmapi.dll",
"/DELAYLOAD:shell32.dll",
"/DELAYLOAD:uxtheme.dll",
]
}
# Subsystem --------------------------------------------------------------------
# This is appended to the subsystem to specify a minimum version.
if (current_cpu == "x64") {
# The number after the comma is the minimum required OS version.
# 5.02 = Windows Server 2003.
subsystem_version_suffix = ",5.02"
} else if (current_cpu == "arm64") {
# Windows ARM64 requires Windows 10.
subsystem_version_suffix = ",10.0"
} else {
# 5.01 = Windows XP.
subsystem_version_suffix = ",5.01"
}
config("console") {
ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
}
config("windowed") {
ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
}
# Incremental linking ----------------------------------------------------------
incremental_linking_on_switch = [ "/INCREMENTAL" ]
incremental_linking_off_switch = [ "/INCREMENTAL:NO" ]
if (is_debug) {
default_incremental_linking_switch = incremental_linking_on_switch
} else {
default_incremental_linking_switch = incremental_linking_off_switch
}
# Applies incremental linking or not depending on the current configuration.
config("default_incremental_linking") {
ldflags = default_incremental_linking_switch
}
# Explicitly on or off incremental linking
config("incremental_linking") {
ldflags = incremental_linking_on_switch
}
config("no_incremental_linking") {
ldflags = incremental_linking_off_switch
}
# Some large modules can't handle incremental linking in some situations. This
# config should be applied to large modules to turn off incremental linking
# when it won't work.
config("default_large_module_incremental_linking") {
if (symbol_level > 0 && (current_cpu == "x86" || !is_component_build)) {
# When symbols are on, things get so large that the tools fail due to the
# size of the .ilk files.
ldflags = incremental_linking_off_switch
} else {
# Otherwise just do the default incremental linking for this build type.
ldflags = default_incremental_linking_switch
}
}
# Character set ----------------------------------------------------------------
# Not including this config means "ansi" (8-bit system codepage).
config("unicode") {
defines = [
"_UNICODE",
"UNICODE",
]
}
# Lean and mean ----------------------------------------------------------------
# Some third party code might not compile with WIN32_LEAN_AND_MEAN so we have
# to have a separate config for it. Remove this config from your target to
# get the "bloaty and accomodating" version of windows.h.
config("lean_and_mean") {
defines = [ "WIN32_LEAN_AND_MEAN" ]
}
# Nominmax --------------------------------------------------------------------
# Some third party code defines NOMINMAX before including windows.h, which
# then causes warnings when it's been previously defined on the command line.
# For such targets, this config can be removed.
config("nominmax") {
defines = [ "NOMINMAX" ]
}

View File

@@ -0,0 +1,39 @@
# 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.
declare_args() {
# Path to Visual Studio. If empty, the default is used which is to use the
# automatic toolchain in depot_tools. If set, you must also set the
# visual_studio_version and wdk_path.
visual_studio_path = ""
# Version of Visual Studio pointed to by the visual_studio_path.
# Use "2013" for Visual Studio 2013, or "2013e" for the Express version.
visual_studio_version = ""
# Directory of the Windows driver kit. If visual_studio_path is empty, this
# will be auto-filled.
wdk_path = ""
# Full path to the Windows SDK, not including a backslash at the end.
# This value is the default location, override if you have a different
# installation location.
windows_sdk_path = "C:\Program Files (x86)\Windows Kits\8.1"
}
if (visual_studio_path == "") {
_toolchain_data =
exec_script("//build/vs_toolchain.py", [ "get_toolchain_dir" ], "scope")
visual_studio_path = _toolchain_data.vs_path
windows_sdk_path = _toolchain_data.sdk_path
visual_studio_version = _toolchain_data.vs_version
wdk_path = _toolchain_data.wdk_dir
visual_studio_runtime_dirs = _toolchain_data.runtime_dirs
} else {
assert(visual_studio_version != "",
"You must set the visual_studio_version if you set the path")
assert(wdk_path != "",
"You must set the wdk_path if you set the visual studio path")
visual_studio_runtime_dirs = []
}

24
engine/src/build/dir_exists.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
#
# Copyright (c) 2011 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 True if the argument is a directory."""
import os.path
import sys
def main():
sys.stdout.write(_is_dir(sys.argv[1]))
return 0
def _is_dir(dir_name):
return str(os.path.isdir(dir_name))
def DoMain(args):
"""Hook to be called from gyp without starting a separate python
interpreter."""
return _is_dir(args[0])
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
# Copyright 2011 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Small utility function to find depot_tools and add it to the python path.
Will throw an ImportError exception if depot_tools can't be found since it
imports breakpad.
This can also be used as a standalone script to print out the depot_tools
directory location.
"""
import os
import sys
# Path to //src
SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
def IsRealDepotTools(path):
expanded_path = os.path.expanduser(path)
return os.path.isfile(os.path.join(expanded_path, 'gclient.py'))
def add_depot_tools_to_path():
"""Search for depot_tools and add it to sys.path."""
# First, check if we have a DEPS'd in "depot_tools".
deps_depot_tools = os.path.join(SRC, 'flutter', 'third_party', 'depot_tools')
if IsRealDepotTools(deps_depot_tools):
# Put the pinned version at the start of the sys.path, in case there
# are other non-pinned versions already on the sys.path.
sys.path.insert(0, deps_depot_tools)
return deps_depot_tools
# Then look if depot_tools is already in PYTHONPATH.
for i in sys.path:
if i.rstrip(os.sep).endswith('depot_tools') and IsRealDepotTools(i):
return i
# Then look if depot_tools is in PATH, common case.
for i in os.environ['PATH'].split(os.pathsep):
if IsRealDepotTools(i):
sys.path.append(i.rstrip(os.sep))
return i
# Rare case, it's not even in PATH, look upward up to root.
root_dir = os.path.dirname(os.path.abspath(__file__))
previous_dir = os.path.abspath(__file__)
while root_dir and root_dir != previous_dir:
i = os.path.join(root_dir, 'depot_tools')
if IsRealDepotTools(i):
sys.path.append(i)
return i
previous_dir = root_dir
root_dir = os.path.dirname(root_dir)
print('Failed to find depot_tools', file=sys.stderr)
return None
DEPOT_TOOLS_PATH = add_depot_tools_to_path()
# pylint: disable=W0611
import breakpad
def main():
if DEPOT_TOOLS_PATH is None:
return 1
print(DEPOT_TOOLS_PATH)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,364 @@
# Copyright 2013 The Flutter 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/fuchsia/config.gni")
import("//build/toolchain/toolchain.gni")
declare_args() {
# The path to where GN targets derived from the Fuchsia SDK are instantiated.
fuchsia_sdk_root = "//build/fuchsia"
# The Flutter buildroot is outside the Fuchsia root and can only use the SDK.
using_fuchsia_sdk = true
# This is set by the dart sources. Once the engine repo switches to using the GN SDK,
# this flag can be unified with `using_fuchsia_sdk`.
using_fuchsia_gn_sdk = false
# The following variables are Flutter buildroot specific.
fuchsia_sdk_path = "//fuchsia/sdk/$host_os"
fuchsia_toolchain_path = "$buildtools_path/${host_os}-${host_cpu}/clang"
}
declare_args() {
# The Skia buildroot uses this flag to decide if it should be using the
# Fuchsia SDK to build its translation units.
skia_using_fuchsia_sdk = using_fuchsia_sdk
}
_fuchsia_sdk_path = "//fuchsia/sdk/$host_os"
_fuchsia_tools_path = "${_fuchsia_sdk_path}/tools/${host_cpu}"
template("_fuchsia_sysroot") {
assert(defined(invoker.meta), "The meta.json file path must be specified.")
assert(target_cpu == "x64" || target_cpu == "arm64",
"We currently only support 'x64' and 'arm64' targets for fuchsia.")
meta_json = read_file(invoker.meta, "json")
assert(meta_json.type == "sysroot")
meta_json_versions = meta_json.versions
if (target_cpu == "x64") {
defs = meta_json_versions.x64
} else {
defs = meta_json_versions.arm64
}
_libs = []
_lib_dirs = []
_include_dirs = []
foreach(link_lib, defs.link_libs) {
if (link_lib != "arch/${target_cpu}/sysroot/lib/Scrt1.o") {
_libs += [ "$_fuchsia_sdk_path/$link_lib" ]
}
}
defs_include_dir = defs.include_dir
_include_dirs += [ "$_fuchsia_sdk_path/$defs_include_dir" ]
config_name = "config_$target_name"
config(config_name) {
lib_dirs = _lib_dirs
libs = _libs
include_dirs = _include_dirs
}
group(target_name) {
public_configs = [ ":$config_name" ]
}
}
template("fuchsia_fidl_library") {
assert(defined(invoker.meta), "The meta.json file path must be specified.")
assert(target_cpu == "x64" || target_cpu == "arm64",
"We currently only support 'x64' and 'arm64' targets for fuchsia.")
meta_json = read_file(invoker.meta, "json")
assert(meta_json.type == "fidl_library")
_deps = [
"//build/fuchsia/pkg:fidl_cpp",
"//build/fuchsia/pkg:fidl_cpp_hlcpp_conversion",
"//build/fuchsia/pkg:fidl_cpp_natural_ostream",
"//build/fuchsia/pkg:fidl_cpp_v2",
"//build/fuchsia/pkg:fidl_cpp_wire",
]
library_name = meta_json.name
library_name_json = "${meta_json.name}.json"
foreach(dep, meta_json.deps) {
# TODO(https://fxbug.dev/42172334): Make zx less special.
if (dep != "zx") {
_deps += [ ":$dep" ]
}
}
config_name = "config_$target_name"
config(config_name) {
include_dirs = [ target_gen_dir ]
}
fidl_gen_target_name = "fidlgen_$target_name"
action(fidl_gen_target_name) {
script = "//build/fuchsia/fidl_gen_cpp.py"
library_name_slashes = string_replace(library_name, ".", "/")
inputs = [ invoker.meta ]
args = [
"--fidlc-bin",
rebase_path("${_fuchsia_tools_path}/fidlc"),
"--sdk-base",
rebase_path(_fuchsia_sdk_path),
"--root",
rebase_path(invoker.meta),
"--json",
rebase_path("$target_gen_dir/$library_name_json"),
]
if (fuchsia_target_api_level != -1) {
args += [
"--target-api-level",
"${fuchsia_target_api_level}",
]
}
outputs = [
"$target_gen_dir/$library_name_slashes/cpp/fidl.cc",
"$target_gen_dir/$library_name_slashes/cpp/fidl.h",
"$target_gen_dir/$library_name_slashes/cpp/fidl_test_base.h",
"$target_gen_dir/$library_name_slashes/cpp/tables.c",
"$target_gen_dir/fidl/$library_name/cpp/common_types.cc",
"$target_gen_dir/fidl/$library_name/cpp/common_types.h",
"$target_gen_dir/fidl/$library_name/cpp/fidl.h",
"$target_gen_dir/fidl/$library_name/cpp/hlcpp_conversion.h",
"$target_gen_dir/fidl/$library_name/cpp/markers.h",
"$target_gen_dir/fidl/$library_name/cpp/natural_messaging.cc",
"$target_gen_dir/fidl/$library_name/cpp/natural_messaging.h",
"$target_gen_dir/fidl/$library_name/cpp/natural_ostream.cc",
"$target_gen_dir/fidl/$library_name/cpp/natural_ostream.h",
"$target_gen_dir/fidl/$library_name/cpp/natural_types.cc",
"$target_gen_dir/fidl/$library_name/cpp/natural_types.h",
"$target_gen_dir/fidl/$library_name/cpp/type_conversions.cc",
"$target_gen_dir/fidl/$library_name/cpp/type_conversions.h",
"$target_gen_dir/fidl/$library_name/cpp/wire.h",
"$target_gen_dir/fidl/$library_name/cpp/wire_messaging.cc",
"$target_gen_dir/fidl/$library_name/cpp/wire_messaging.h",
"$target_gen_dir/fidl/$library_name/cpp/wire_test_base.h",
"$target_gen_dir/fidl/$library_name/cpp/wire_types.cc",
"$target_gen_dir/fidl/$library_name/cpp/wire_types.h",
]
args += [
"--fidlgen-bin",
rebase_path("${_fuchsia_tools_path}/fidlgen_cpp"),
"--fidlgen-bin",
rebase_path("${_fuchsia_tools_path}/fidlgen_hlcpp"),
"--fidlgen-output-root",
rebase_path("$target_gen_dir"),
]
}
source_set(target_name) {
public_configs = [ ":$config_name" ]
sources = get_target_outputs(":$fidl_gen_target_name")
deps = [ ":$fidl_gen_target_name" ]
public_deps = _deps
}
}
template("_fuchsia_cc_source_library") {
assert(defined(invoker.meta), "The meta.json file path must be specified.")
meta_json = read_file(invoker.meta, "json")
assert(meta_json.type == "cc_source_library")
_output_name = meta_json.name
_include_dirs = []
_public_headers = []
_sources = []
_deps = []
meta_json_include_dir = meta_json.include_dir
_include_dirs += [ "$_fuchsia_sdk_path/$meta_json_include_dir" ]
foreach(header, meta_json.headers) {
rebased_header = []
rebased_header = [ "$_fuchsia_sdk_path/$header" ]
_public_headers += rebased_header
_sources += rebased_header
}
foreach(source, meta_json.sources) {
_sources += [ "$_fuchsia_sdk_path/$source" ]
}
config_name = "config_$target_name"
config(config_name) {
include_dirs = _include_dirs
}
foreach(dep, meta_json.deps) {
_deps += [ "../pkg:$dep" ]
}
foreach(dep, meta_json.fidl_deps) {
_deps += [ "../fidl:$dep" ]
}
foreach(binding_dep, meta_json.fidl_binding_deps) {
# No need to check "binding_deps.binding_type" because we always
# generate both hlcpp and natural bindings.
foreach(dep, binding_dep.deps) {
_deps += [ "../fidl:$dep" ]
}
}
source_set(target_name) {
output_name = _output_name
public = _public_headers
sources = _sources
public_configs = [ ":$config_name" ]
public_deps = _deps
}
}
template("_fuchsia_cc_prebuilt_library") {
assert(defined(invoker.meta), "The meta.json file path must be specified.")
meta_json = read_file(invoker.meta, "json")
_include_dirs = []
_deps = []
_libs = []
meta_json_include_dir = meta_json.include_dir
_include_dirs += [ "$_fuchsia_sdk_path/$meta_json_include_dir" ]
foreach(dep, meta_json.deps) {
_deps += [ ":$dep" ]
}
meta_json_binaries = meta_json.binaries
if (target_cpu == "x64") {
meta_json_binaries_arch = meta_json_binaries.x64
} else {
meta_json_binaries_arch = meta_json_binaries.arm64
}
prebuilt_lib = meta_json_binaries_arch.link
_libs = [ "$_fuchsia_sdk_path/$prebuilt_lib" ]
config_name = "config_$target_name"
config(config_name) {
include_dirs = _include_dirs
libs = _libs
}
group(target_name) {
public_configs = [ ":$config_name" ]
public_deps = _deps
}
}
template("fuchsia_sdk") {
assert(defined(invoker.meta), "The meta.json file path must be specified.")
assert(defined(invoker.enabled_parts),
"A list containing the parts of the SDK to generate targets for.")
meta_json = read_file(invoker.meta, "json")
foreach(part, meta_json.parts) {
part_meta_json = {
}
part_meta = part.meta
part_meta_rebased = "$_fuchsia_sdk_path/$part_meta"
# Check if the part is using `part.element_type` or `part.type`.
part_type = ""
if (defined(part.element_type)) {
part_type = part.element_type
} else if (defined(part.type)) {
part_type = part.type
}
# Check if the part type is in `invoker.enabled_parts`.
if (invoker.enabled_parts + [ part_type ] - [ part_type ] !=
invoker.enabled_parts) {
part_meta_json = read_file(part_meta_rebased, "json")
subtarget_name = part_meta_json.name
if (part_type == "cc_source_library") {
_fuchsia_cc_source_library(subtarget_name) {
meta = part_meta_rebased
}
} else if (part_type == "sysroot") {
_fuchsia_sysroot(subtarget_name) {
meta = part_meta_rebased
}
} else if (part_type == "fidl_library") {
# TODO(https://fxbug.dev/42172334): Make zx less special.
if (subtarget_name != "zx") {
fuchsia_fidl_library(subtarget_name) {
meta = part_meta_rebased
}
}
} else if (part_type == "cc_prebuilt_library") {
_fuchsia_cc_prebuilt_library(subtarget_name) {
meta = part_meta_rebased
}
}
}
}
group(target_name) {
}
}
template("fuchsia_repo") {
assert(defined(invoker.archives),
"The list of archives to publish must be specified.")
assert(defined(invoker.repo), "The location of the repo should be specified.")
action(target_name) {
script = "//flutter/tools/fuchsia/gen_repo.py"
pm_binary = rebase_path("${_fuchsia_tools_path}/pm")
repo_directory = invoker.repo
inputs = [ pm_binary ]
archive_flags = []
foreach(archive, invoker.archives) {
assert(get_path_info(archive, "extension") == "far",
"Archive '$archive' does not have the .far extension.")
inputs += [ archive ]
archive_flags += [
"--archive",
rebase_path(archive),
]
}
outputs = [ repo_directory ]
args = [
"--pm-bin",
pm_binary,
"--repo-dir",
rebase_path(repo_directory),
] + archive_flags
if (defined(invoker.deps)) {
deps = invoker.deps
}
}
}

View File

@@ -0,0 +1,60 @@
#!/bin/sh
submodule_diff() {
if test -n "$2"; then
git diff-tree -r --ignore-submodules=dirty "$1" "$2" | grep -e '^:160000' -e '^:...... 160000' | xargs
else
git diff-index --cached --ignore-submodules=dirty "$1" | grep -e '^:160000' -e '^:...... 160000' | xargs
fi
}
if git rev-parse --verify --quiet --no-revs MERGE_HEAD; then
merge_base=$(git merge-base HEAD MERGE_HEAD)
if test -z "$(submodule_diff $merge_base HEAD)"; then
# Most up-to-date submodules are in MERGE_HEAD.
head_ref=MERGE_HEAD
else
# Most up-to-date submodules are in HEAD.
head_ref=HEAD
fi
else
# No merge in progress. Submodules must match HEAD.
head_ref=HEAD
fi
submods=$(submodule_diff $head_ref)
if test "$submods"; then
echo "You are trying to commit changes to the following submodules:" 1>&2
echo 1>&2
echo $submods | cut -d ' ' -f 6 | sed 's/^/ /g' 1>&2
cat <<EOF 1>&2
Submodule commits are not allowed. Please run:
git status --ignore-submodules=dirty
and/or:
git diff-index --cached --ignore-submodules=dirty HEAD
... to see what's in your index.
If you're really and truly trying to roll the version of a submodule, you should
commit the new version to DEPS, instead.
EOF
exit 1
fi
gitmodules_diff() {
git diff-index --cached "$1" .gitmodules
}
if [ "$(git ls-files .gitmodules)" ] && [ "$(gitmodules_diff $head_ref)" ]; then
cat <<EOF 1>&2
You are trying to commit a change to .gitmodules. That is not allowed.
To make changes to submodule names/paths, edit DEPS.
EOF
exit 1
fi
exit 0

View File

@@ -0,0 +1,133 @@
# 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 sys
"""Helper functions useful when writing scripts that are run from GN's
exec_script function."""
class GNError(Exception):
pass
# Computes ASCII code of an element of encoded Python 2 str / Python 3 bytes.
_Ord = ord if sys.version_info.major < 3 else lambda c: c
def _TranslateToGnChars(s):
for decoded_ch in s.encode('utf-8'): # str in Python 2, bytes in Python 3.
code = _Ord(decoded_ch) # int
if code in (34, 36, 92): # For '"', '$', or '\\'.
yield '\\' + chr(code)
elif 32 <= code < 127:
yield chr(code)
else:
yield '$0x%02X' % code
def ToGNString(value, pretty=False):
"""Returns a stringified GN equivalent of a Python value.
Args:
value: The Python value to convert.
pretty: Whether to pretty print. If true, then non-empty lists are rendered
recursively with one item per line, with indents. Otherwise lists are
rendered without new line.
Returns:
The stringified GN equivalent to |value|.
Raises:
GNError: |value| cannot be printed to GN.
"""
if sys.version_info.major < 3:
basestring_compat = basestring
else:
basestring_compat = str
# Emits all output tokens without intervening whitespaces.
def GenerateTokens(v, level):
if isinstance(v, basestring_compat):
yield '"' + ''.join(_TranslateToGnChars(v)) + '"'
elif isinstance(v, bool):
yield 'true' if v else 'false'
elif isinstance(v, int):
yield str(v)
elif isinstance(v, list):
yield '['
for i, item in enumerate(v):
if i > 0:
yield ','
for tok in GenerateTokens(item, level + 1):
yield tok
yield ']'
elif isinstance(v, dict):
if level > 0:
yield '{'
for key in sorted(v):
if not isinstance(key, basestring_compat):
raise GNError('Dictionary key is not a string.')
if not key or key[0].isdigit() or not key.replace('_', '').isalnum():
raise GNError('Dictionary key is not a valid GN identifier.')
yield key # No quotations.
yield '='
for tok in GenerateTokens(v[key], level + 1):
yield tok
if level > 0:
yield '}'
else: # Not supporting float: Add only when needed.
raise GNError('Unsupported type when printing to GN.')
can_start = lambda tok: tok and tok not in ',}]='
can_end = lambda tok: tok and tok not in ',{[='
# Adds whitespaces, trying to keep everything (except dicts) in 1 line.
def PlainGlue(gen):
prev_tok = None
for i, tok in enumerate(gen):
if i > 0:
if can_end(prev_tok) and can_start(tok):
yield '\n' # New dict item.
elif prev_tok == '[' and tok == ']':
yield ' ' # Special case for [].
elif tok != ',':
yield ' '
yield tok
prev_tok = tok
# Adds whitespaces so non-empty lists can span multiple lines, with indent.
def PrettyGlue(gen):
prev_tok = None
level = 0
for i, tok in enumerate(gen):
if i > 0:
if can_end(prev_tok) and can_start(tok):
yield '\n' + ' ' * level # New dict item.
elif tok == '=' or prev_tok in '=':
yield ' ' # Separator before and after '=', on same line.
if tok in ']}':
level -= 1
# Exclude '[]' and '{}' cases.
if int(prev_tok == '[') + int(tok == ']') == 1 or \
int(prev_tok == '{') + int(tok == '}') == 1:
yield '\n' + ' ' * level
yield tok
if tok in '[{':
level += 1
if tok == ',':
yield '\n' + ' ' * level
prev_tok = tok
token_gen = GenerateTokens(value, 0)
ret = ''.join((PrettyGlue if pretty else PlainGlue)(token_gen))
# Add terminating '\n' for dict |value| or multi-line output.
if isinstance(value, dict) or '\n' in ret:
return ret + '\n'
return ret

View File

@@ -0,0 +1,28 @@
# 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.
"""Helper script for GN to run an arbitrary binary. See compiled_action.gni.
Run with:
python gn_run_binary.py <binary_name> [args ...]
"""
import sys
import subprocess
# This script is designed to run binaries produced by the current build. We
# always prefix it with "./" to avoid picking up system versions that might
# also be on the path.
path = './' + sys.argv[1]
# The rest of the arguements are passed directly to the executable.
args = [path] + sys.argv[2:]
try:
subprocess.check_output(args, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as ex:
print("Command failed: " + ' '.join(args))
print("exitCode: " + str(ex.returncode))
print(ex.output.decode('utf-8', errors='replace'))
sys.exit(ex.returncode)

View File

@@ -0,0 +1,54 @@
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Helper script for GN to run malioc.
This is the same as `gn_run_binary.py`, except an extra parameter is included
for the malioc output file. When the malioc run fails, errors are placed in the
json output file. This script attempts to read the output file and dump it to
stdout upon failure.
Run with:
python gn_run_malioc.py <binary_name> <output_path> [args ...]
"""
import json
import os
import sys
import subprocess
# This script is designed to run binaries produced by the current build. We
# always prefix it with "./" to avoid picking up system versions that might
# also be on the path.
path = './' + sys.argv[1]
malioc_output = sys.argv[2]
# The rest of the arguements are passed directly to the executable.
args = [path, '--output', malioc_output] + sys.argv[3:]
try:
subprocess.check_output(args, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as ex:
print(ex.output.decode('utf-8', errors='replace'))
if os.path.exists(malioc_output):
with open(malioc_output, 'r') as malioc_file:
malioc_json = malioc_file.read()
print('malioc output:')
# Attempt to pretty print the json output, but fall back to printing the
# raw output if doing so fails.
try:
parsed = json.loads(malioc_json)
print(json.dumps(parsed, indent=2))
except:
print(malioc_json)
else:
print(
'Unable to find the malioc output file in order to print contained'
'errors:',
malioc_output,
)
sys.exit(ex.returncode)

View File

@@ -0,0 +1,24 @@
Internal property sheets:
essential.vsprops
Contains the common settings used throughout the projects. Is included by either ..\debug.vsprops or ..\release.vsprops, so in general, it is not included directly.
release_defaults.vsprops
Included by ..\release.vsprops. Its settings are overriden by release_impl$(CHROME_BUILD_TYPE).vsprops. Uses the default VS setting which is "Maximize Speed". Results in relatively fast build with reasonable optimization level but without whole program optimization to reduce build time.
release_impl.vsprops
Included by ..\release.vsprops by default when CHROME_BUILD_TYPE is undefined. Includes release_defaults.vsprops.
release_impl_checksenabled.vsprops
Included by ..\release.vsprops when CHROME_BUILD_TYPE=_checksenabled. Matches what release_defaults.vsprops does, but doesn't actually inherit from it as we couldn't quite get that working. The only difference is that _DEBUG is set instead of NDEBUG. Used for keeping debug checks enabled with a build that is fast enough to dogfood with.
release_impl_official.vsprops
Included by ..\release.vsprops when CHROME_BUILD_TYPE=_official. Includes release_defaults.vsprops. Enables Whole Program Optimizations (WPO), which doubles the build time. Results in much more optimized build. Uses "Full Optimization" and "Flavor small code".
release_impl_pgo_instrument.vsprops
Included by ..\release.vsprops when CHROME_BUILD_TYPE=_pgo_instrument. Includes release_defaults.vsprops. Enables Profile Guided Optimization (PGO) instrumentation (first pass). Uses "Full Optimization" and "Flavor small code".
release_impl_pgo_optimize.vsprops
Included by ..\release.vsprops when CHROME_BUILD_TYPE=_pgo_optimize. Includes release_defaults.vsprops. Enables Profile Guided Optimization (PGO) optimization (second pass). Uses "Full Optimization" and "Flavor small code".
release_impl_purify.vsprops
Included by ..\release.vsprops when CHROME_BUILD_TYPE=_purify. Includes release_defaults.vsprops. Disables optimizations. Used with Purify to test without debug tools and without optimization; i.e. NDEBUG is defined but the compiler doesn't optimize the binary.

View File

@@ -0,0 +1 @@
0a9b8f68615ce388b65201e6d22da7a9cf2e729c

View File

@@ -0,0 +1,29 @@
# -*- python -*-
# Crocodile config file for Chromium linux
# TODO(jhawkins): We'll need to add a chromeos.croc once we get a coverage bot
# for that platform.
{
# List of rules, applied in order
'rules' : [
# Specify inclusions before exclusions, since rules are in order.
# Don't include non-Linux platform dirs
{
'regexp' : '.*/(chromeos|views)/',
'include' : 0,
},
# Don't include chromeos, windows, or mac specific files
{
'regexp' : '.*(_|/)(chromeos|mac|win|views)(\\.|_)',
'include' : 0,
},
# Groups
{
'regexp' : '.*_test_linux\\.',
'group' : 'test',
},
],
}

View File

@@ -0,0 +1,29 @@
# Copyright 2015 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.
# Helper script to run dump_syms on Chrome Linux executables and strip
# them if needed.
import os
import subprocess
import sys
if len(sys.argv) != 5:
print("dump_app_syms.py <dump_syms_exe> <strip_binary>")
print(" <binary_with_symbols> <symbols_output>")
sys.exit(1)
dumpsyms = sys.argv[1]
strip_binary = sys.argv[2]
infile = sys.argv[3]
outfile = sys.argv[4]
# Dump only when the output file is out-of-date.
if not os.path.isfile(outfile) or \
os.stat(outfile).st_mtime > os.stat(infile).st_mtime:
with open(outfile, 'w') as outfileobj:
subprocess.check_call([dumpsyms, '-r', infile], stdout=outfileobj)
if strip_binary != '0':
subprocess.check_call(['strip', infile])

View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Copyright 2013 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.
# Script to install the Chrome OS fonts on Linux.
# This script can be run manually (as root), but is also run as part
# install-build-deps.sh.
import os
import shutil
import subprocess
import sys
# Taken from the media-fonts/notofonts ebuild in chromiumos-overlay.
VERSION = '20140815'
URL = ('https://commondatastorage.googleapis.com/chromeos-localmirror/'
'distfiles/notofonts-%s.tar.bz2') % (VERSION)
FONTS_DIR = '/usr/local/share/fonts'
def main(args):
if not sys.platform.startswith('linux'):
print("Error: %s must be run on Linux." % __file__)
return 1
if os.getuid() != 0:
print("Error: %s must be run as root." % __file__)
return 1
if not os.path.isdir(FONTS_DIR):
print("Error: Destination directory does not exist: %s" % FONTS_DIR)
return 1
dest_dir = os.path.join(FONTS_DIR, 'chromeos')
stamp = os.path.join(dest_dir, ".stamp02")
if os.path.exists(stamp):
with open(stamp) as s:
if s.read() == URL:
print("Chrome OS fonts already up-to-date in %s." % dest_dir)
return 0
if os.path.isdir(dest_dir):
shutil.rmtree(dest_dir)
os.mkdir(dest_dir)
os.chmod(dest_dir, 0o755)
print("Installing Chrome OS fonts to %s." % dest_dir)
tarball = os.path.join(dest_dir, os.path.basename(URL))
subprocess.check_call(['curl', '-L', URL, '-o', tarball])
subprocess.check_call(['tar', '--no-same-owner', '--no-same-permissions',
'-xf', tarball, '-C', dest_dir])
os.remove(tarball)
readme = os.path.join(dest_dir, "README")
with open(readme, 'w') as s:
s.write("This directory and its contents are auto-generated.\n")
s.write("It may be deleted and recreated. Do not modify.\n")
s.write("Script: %s\n" % __file__)
with open(stamp, 'w') as s:
s.write(URL)
for base, dirs, files in os.walk(dest_dir):
for dir in dirs:
os.chmod(os.path.join(base, dir), 0o755)
for file in files:
os.chmod(os.path.join(base, file), 0o644)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

View File

@@ -0,0 +1,59 @@
#!/bin/bash
# Copyright (c) 2012 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 program wraps around pkg-config to generate the correct include and
# library paths when cross-compiling using a sysroot.
# The assumption is that the sysroot contains the .pc files in usr/lib/pkgconfig
# and usr/share/pkgconfig (relative to the sysroot) and that they output paths
# relative to some parent path of the sysroot.
# This assumption is valid for a range of sysroots, in particular: a
# LSB-compliant root filesystem mounted at the sysroot, and a board build
# directory of a Chromium OS chroot.
# Additional directories containing .pc files may be specified by setting
# the PKG_CONFIG_PATH environment variable- these will be prepended to the
# generated paths.
root="$1"
shift
target_arch="$1"
shift
libpath="$1"
shift
if [ -z "$root" -o -z "$target_arch" ]
then
echo "usage: $0 /path/to/sysroot target_arch libdir [pkg-config-arguments] package" >&2
exit 1
fi
if [ "$target_arch" = "x64" ]
then
: ${libpath:="lib64"}
else
: ${libpath:="lib"}
fi
rewrite=`dirname $0`/rewrite_dirs.py
package=${!#}
config_path=$root/usr/$libpath/pkgconfig:$root/usr/share/pkgconfig
# prepend any paths specified by the environment
if [ -n "$PKG_CONFIG_PATH" ]
then
config_path="$PKG_CONFIG_PATH:$config_path"
fi
set -e
# Some sysroots, like the Chromium OS ones, may generate paths that are not
# relative to the sysroot. For example,
# /path/to/chroot/build/x86-generic/usr/lib/pkgconfig/pkg.pc may have all paths
# relative to /path/to/chroot (i.e. prefix=/build/x86-generic/usr) instead of
# relative to /path/to/chroot/build/x86-generic (i.e prefix=/usr).
# To support this correctly, it's necessary to extract the prefix to strip from
# pkg-config's |prefix| variable.
prefix=`PKG_CONFIG_PATH=$config_path pkg-config --variable=prefix "$package" | sed -e 's|/usr$||'`
result=`PKG_CONFIG_PATH=$config_path pkg-config "$@"`
echo "$result"| $rewrite --sysroot "$root" --strip-prefix "$prefix"

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
#
# Copyright (c) 2011 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.
"""Rewrites paths in -I, -L and other option to be relative to a sysroot."""
import sys
import os
import optparse
REWRITE_PREFIX = ['-I',
'-idirafter',
'-imacros',
'-imultilib',
'-include',
'-iprefix',
'-iquote',
'-isystem',
'-L']
def RewritePath(path, opts):
"""Rewrites a path by stripping the prefix and prepending the sysroot."""
sysroot = opts.sysroot
prefix = opts.strip_prefix
if os.path.isabs(path) and not path.startswith(sysroot):
if path.startswith(prefix):
path = path[len(prefix):]
path = path.lstrip('/')
return os.path.join(sysroot, path)
else:
return path
def RewriteLine(line, opts):
"""Rewrites all the paths in recognized options."""
args = line.split()
count = len(args)
i = 0
while i < count:
for prefix in REWRITE_PREFIX:
# The option can be either in the form "-I /path/to/dir" or
# "-I/path/to/dir" so handle both.
if args[i] == prefix:
i += 1
try:
args[i] = RewritePath(args[i], opts)
except IndexError:
sys.stderr.write('Missing argument following %s\n' % prefix)
break
elif args[i].startswith(prefix):
args[i] = prefix + RewritePath(args[i][len(prefix):], opts)
i += 1
return ' '.join(args)
def main(argv):
parser = optparse.OptionParser()
parser.add_option('-s', '--sysroot', default='/', help='sysroot to prepend')
parser.add_option('-p', '--strip-prefix', default='', help='prefix to strip')
opts, args = parser.parse_args(argv[1:])
for line in sys.stdin.readlines():
line = RewriteLine(line.strip(), opts)
print(line)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))

View File

@@ -0,0 +1,100 @@
#!/bin/sh
# Copyright (c) 2013 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.
# Reads etc/ld.so.conf and/or etc/ld.so.conf.d/*.conf and returns the
# appropriate linker flags.
#
# sysroot_ld_path.sh /abspath/to/sysroot
#
log_error_and_exit() {
echo $0: $@
exit 1
}
process_entry() {
if [ -z "$1" ] || [ -z "$2" ]; then
log_error_and_exit "bad arguments to process_entry()"
fi
local root="$1"
local localpath="$2"
echo $localpath | grep -qs '^/'
if [ $? -ne 0 ]; then
log_error_and_exit $localpath does not start with /
fi
local entry="$root$localpath"
echo -L$entry
echo -Wl,-rpath-link=$entry
}
process_ld_so_conf() {
if [ -z "$1" ] || [ -z "$2" ]; then
log_error_and_exit "bad arguments to process_ld_so_conf()"
fi
local root="$1"
local ld_so_conf="$2"
# ld.so.conf may include relative include paths. pushd is a bashism.
local saved_pwd=$(pwd)
cd $(dirname "$ld_so_conf")
cat "$ld_so_conf" | \
while read ENTRY; do
echo "$ENTRY" | grep -qs ^include
if [ $? -eq 0 ]; then
local included_files=$(echo "$ENTRY" | sed 's/^include //')
echo "$included_files" | grep -qs ^/
if [ $? -eq 0 ]; then
if ls $root$included_files >/dev/null 2>&1 ; then
for inc_file in $root$included_files; do
process_ld_so_conf "$root" "$inc_file"
done
fi
else
if ls $(pwd)/$included_files >/dev/null 2>&1 ; then
for inc_file in $(pwd)/$included_files; do
process_ld_so_conf "$root" "$inc_file"
done
fi
fi
continue
fi
echo "$ENTRY" | grep -qs ^/
if [ $? -eq 0 ]; then
process_entry "$root" "$ENTRY"
fi
done
# popd is a bashism
cd "$saved_pwd"
}
# Main
if [ $# -ne 1 ]; then
echo Usage $0 /abspath/to/sysroot
exit 1
fi
echo $1 | grep -qs ' '
if [ $? -eq 0 ]; then
log_error_and_exit $1 contains whitespace.
fi
LD_SO_CONF="$1/etc/ld.so.conf"
LD_SO_CONF_D="$1/etc/ld.so.conf.d"
if [ -e "$LD_SO_CONF" ]; then
process_ld_so_conf "$1" "$LD_SO_CONF" | xargs echo
elif [ -e "$LD_SO_CONF_D" ]; then
find "$LD_SO_CONF_D" -maxdepth 1 -name '*.conf' -print -quit > /dev/null
if [ $? -eq 0 ]; then
for entry in $LD_SO_CONF_D/*.conf; do
process_ld_so_conf "$1" "$entry"
done | xargs echo
fi
fi

View File

@@ -0,0 +1,166 @@
#!/usr/bin/env python3
#
# Copyright (c) 2013 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.
"""Install Debian sysroots for building chromium.
"""
# The sysroot is needed to ensure that binaries that get built will run on
# the oldest stable version of Debian that we currently support.
# This script can be run manually but is more often run as part of gclient
# hooks. When run from hooks this script is a no-op on non-linux platforms.
# The sysroot image could be constructed from scratch based on the current state
# of the Debian archive but for consistency we use a pre-built root image (we
# don't want upstream changes to Debian to effect the chromium build until we
# choose to pull them in). The images will normally need to be rebuilt every
# time chrome's build dependencies are changed but should also be updated
# periodically to include upstream security fixes from Debian.
import hashlib
import json
import platform
import optparse
import os
import re
import shutil
import subprocess
import sys
try:
# For Python 3.0 and later
from urllib.request import urlopen
except ImportError:
# Fall back to Python 2's urllib2
from urllib.request import urlopen
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
URL_PREFIX = 'https://commondatastorage.googleapis.com'
URL_PATH = 'chrome-linux-sysroot/toolchain'
VALID_ARCHS = ('arm', 'arm64', 'i386', 'amd64')
ARCH_TRANSLATIONS = {
'x64': 'amd64',
'x86': 'i386',
}
DEFAULT_TARGET_PLATFORM = 'sid'
class Error(Exception):
pass
def GetSha1(filename):
sha1 = hashlib.sha1()
with open(filename, 'rb') as f:
while True:
# Read in 1mb chunks, so it doesn't all have to be loaded into memory.
chunk = f.read(1024*1024)
if not chunk:
break
sha1.update(chunk)
return sha1.hexdigest()
def main(args):
parser = optparse.OptionParser('usage: %prog [OPTIONS]', description=__doc__)
parser.add_option('--arch',
help='Sysroot architecture: %s' % ', '.join(VALID_ARCHS))
parser.add_option('--all', action='store_true',
help='Install all sysroot images (useful when updating the'
' images)')
parser.add_option('--print-hash',
help='Print the hash of the sysroot for the given arch.')
options, _ = parser.parse_args(args)
if not sys.platform.startswith('linux'):
return 0
if options.print_hash:
arch = options.print_hash
print(GetSysrootDict(DEFAULT_TARGET_PLATFORM,
ARCH_TRANSLATIONS.get(arch, arch))['Sha1Sum'])
return 0
if options.arch:
InstallSysroot(DEFAULT_TARGET_PLATFORM,
ARCH_TRANSLATIONS.get(options.arch, options.arch))
elif options.all:
for arch in VALID_ARCHS:
InstallSysroot(DEFAULT_TARGET_PLATFORM, arch)
else:
print('You much specify one of the options.')
return 1
return 0
def GetSysrootDict(target_platform, target_arch):
if target_arch not in VALID_ARCHS:
raise Error('Unknown architecture: %s' % target_arch)
sysroots_file = os.path.join(SCRIPT_DIR, 'sysroots.json')
sysroots = json.load(open(sysroots_file))
sysroot_key = '%s_%s' % (target_platform, target_arch)
if sysroot_key not in sysroots:
raise Error('No sysroot for: %s %s' % (target_platform, target_arch))
return sysroots[sysroot_key]
def InstallSysroot(target_platform, target_arch):
sysroot_dict = GetSysrootDict(target_platform, target_arch)
tarball_filename = sysroot_dict['Tarball']
tarball_sha1sum = sysroot_dict['Sha1Sum']
# TODO(thestig) Consider putting this elsewhere to avoid having to recreate
# it on every build.
linux_dir = os.path.dirname(SCRIPT_DIR)
sysroot = os.path.join(linux_dir, sysroot_dict['SysrootDir'])
url = '%s/%s/%s/%s' % (URL_PREFIX, URL_PATH, tarball_sha1sum,
tarball_filename)
stamp = os.path.join(sysroot, '.stamp')
if os.path.exists(stamp):
with open(stamp) as s:
if s.read() == url:
return
print('Installing Debian %s %s root image: %s' % \
(target_platform, target_arch, sysroot))
if os.path.isdir(sysroot):
shutil.rmtree(sysroot)
os.mkdir(sysroot)
tarball = os.path.join(sysroot, tarball_filename)
print('Downloading %s' % url)
sys.stdout.flush()
sys.stderr.flush()
for _ in range(3):
try:
response = urlopen(url)
with open(tarball, "wb") as f:
f.write(response.read())
break
except Exception: # Ignore exceptions.
pass
else:
raise Error('Failed to download %s' % url)
sha1sum = GetSha1(tarball)
if sha1sum != tarball_sha1sum:
raise Error('Tarball sha1sum is wrong.'
'Expected %s, actual: %s' % (tarball_sha1sum, sha1sum))
subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot])
os.remove(tarball)
with open(stamp, 'w') as s:
s.write(url)
if __name__ == '__main__':
try:
sys.exit(main(sys.argv[1:]))
except Error as e:
sys.stderr.write(str(e) + '\n')
sys.exit(1)

View File

@@ -0,0 +1,27 @@
{
"sid_amd64": {
"Sha1Sum": "79a7783607a69b6f439add567eb6fcb48877085c",
"SysrootDir": "debian_sid_amd64-sysroot",
"Tarball": "debian_sid_amd64_sysroot.tar.xz"
},
"sid_arm": {
"Sha1Sum": "3fcc1d4e44127006318371002a0f421a4fde2ab4",
"SysrootDir": "debian_sid_arm-sysroot",
"Tarball": "debian_sid_arm_sysroot.tar.xz"
},
"sid_arm64": {
"Sha1Sum": "2cade9ee1ca9186b28ac768c19e1ab7c45ee0600",
"SysrootDir": "debian_sid_arm64-sysroot",
"Tarball": "debian_sid_arm64_sysroot.tar.xz"
},
"sid_armel": {
"Sha1Sum": "72aecf0a5603919b41cfb0766fe511c34933e915",
"SysrootDir": "debian_sid_armel-sysroot",
"Tarball": "debian_sid_armel_sysroot.tar.xz"
},
"sid_i386": {
"Sha1Sum": "e954fb79fcddf64bc39d721c9a5b652b6da549fa",
"SysrootDir": "debian_sid_i386-sysroot",
"Tarball": "debian_sid_i386_sysroot.tar.xz"
}
}

39
engine/src/build/ls.py Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env python3
#
# Copyright 2015 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.
"""Recursively list files of the target directory. Ignores dot files."""
import argparse
import os
import sys
def main(target_directory, file_extension):
for root, dirs, files in os.walk(target_directory):
files = [f for f in files if not f[0] == '.']
dirs[:] = [d for d in dirs if not d[0] == '.']
for f in files:
if file_extension is None or os.path.splitext(f)[-1] == file_extension:
path = os.path.join(root, f)
print(path)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Recursively list files of the target directory")
parser.add_argument("--target-directory",
dest="target_directory",
metavar="<target-directory>",
type=str,
required=True,
help="The target directory")
parser.add_argument("--file-extension",
dest="file_extension",
metavar="<file-extension>",
type=str,
required=False,
help="File extension to filter")
args = parser.parse_args()
sys.exit(main(args.target_directory, args.file_extension))

View File

@@ -0,0 +1,270 @@
#!/usr/bin/env python3
#
# Copyright (c) 2011 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.
"""Usage: change_mach_o_flags.py [--executable-heap] [--no-pie] <executablepath>
Arranges for the executable at |executable_path| to have its data (heap)
pages protected to prevent execution on Mac OS X 10.7 ("Lion"), and to have
the PIE (position independent executable) bit set to enable ASLR (address
space layout randomization). With --executable-heap or --no-pie, the
respective bits are cleared instead of set, making the heap executable or
disabling PIE/ASLR.
This script is able to operate on thin (single-architecture) Mach-O files
and fat (universal, multi-architecture) files. When operating on fat files,
it will set or clear the bits for each architecture contained therein.
NON-EXECUTABLE HEAP
Traditionally in Mac OS X, 32-bit processes did not have data pages set to
prohibit execution. Although user programs could call mprotect and
mach_vm_protect to deny execution of code in data pages, the kernel would
silently ignore such requests without updating the page tables, and the
hardware would happily execute code on such pages. 64-bit processes were
always given proper hardware protection of data pages. This behavior was
controllable on a system-wide level via the vm.allow_data_exec sysctl, which
is set by default to 1. The bit with value 1 (set by default) allows code
execution on data pages for 32-bit processes, and the bit with value 2
(clear by default) does the same for 64-bit processes.
In Mac OS X 10.7, executables can "opt in" to having hardware protection
against code execution on data pages applied. This is done by setting a new
bit in the |flags| field of an executable's |mach_header|. When
MH_NO_HEAP_EXECUTION is set, proper protections will be applied, regardless
of the setting of vm.allow_data_exec. See xnu-1699.22.73/osfmk/vm/vm_map.c
override_nx and xnu-1699.22.73/bsd/kern/mach_loader.c load_machfile.
The Apple toolchain has been revised to set the MH_NO_HEAP_EXECUTION when
producing executables, provided that -allow_heap_execute is not specified
at link time. Only linkers shipping with Xcode 4.0 and later (ld64-123.2 and
later) have this ability. See ld64-123.2.1/src/ld/Options.cpp
Options::reconfigureDefaults() and
ld64-123.2.1/src/ld/HeaderAndLoadCommands.hpp
HeaderAndLoadCommandsAtom<A>::flags().
This script sets the MH_NO_HEAP_EXECUTION bit on Mach-O executables. It is
intended for use with executables produced by a linker that predates Apple's
modifications to set this bit itself. It is also useful for setting this bit
for non-i386 executables, including x86_64 executables. Apple's linker only
sets it for 32-bit i386 executables, presumably under the assumption that
the value of vm.allow_data_exec is set in stone. However, if someone were to
change vm.allow_data_exec to 2 or 3, 64-bit x86_64 executables would run
without hardware protection against code execution on data pages. This
script can set the bit for x86_64 executables, guaranteeing that they run
with appropriate protection even when vm.allow_data_exec has been tampered
with.
POSITION-INDEPENDENT EXECUTABLES/ADDRESS SPACE LAYOUT RANDOMIZATION
This script sets or clears the MH_PIE bit in an executable's Mach-O header,
enabling or disabling position independence on Mac OS X 10.5 and later.
Processes running position-independent executables have varying levels of
ASLR protection depending on the OS release. The main executable's load
address, shared library load addresess, and the heap and stack base
addresses may be randomized. Position-independent executables are produced
by supplying the -pie flag to the linker (or defeated by supplying -no_pie).
Executables linked with a deployment target of 10.7 or higher have PIE on
by default.
This script is never strictly needed during the build to enable PIE, as all
linkers used are recent enough to support -pie. However, it's used to
disable the PIE bit as needed on already-linked executables.
"""
import optparse
import os
import struct
import sys
# <mach-o/fat.h>
FAT_MAGIC = 0xcafebabe
FAT_CIGAM = 0xbebafeca
# <mach-o/loader.h>
MH_MAGIC = 0xfeedface
MH_CIGAM = 0xcefaedfe
MH_MAGIC_64 = 0xfeedfacf
MH_CIGAM_64 = 0xcffaedfe
MH_EXECUTE = 0x2
MH_PIE = 0x00200000
MH_NO_HEAP_EXECUTION = 0x01000000
class MachOError(Exception):
"""A class for exceptions thrown by this module."""
pass
def CheckedSeek(file, offset):
"""Seeks the file-like object at |file| to offset |offset| and raises a
MachOError if anything funny happens."""
file.seek(offset, os.SEEK_SET)
new_offset = file.tell()
if new_offset != offset:
raise MachOError('seek: expected offset %d, observed %d' % (offset, new_offset))
def CheckedRead(file, count):
"""Reads |count| bytes from the file-like |file| object, raising a
MachOError if any other number of bytes is read."""
bytes = file.read(count)
if len(bytes) != count:
raise MachOError('read: expected length %d, observed %d' % (count, len(bytes)))
return bytes
def ReadUInt32(file, endian):
"""Reads an unsinged 32-bit integer from the file-like |file| object,
treating it as having endianness specified by |endian| (per the |struct|
module), and returns it as a number. Raises a MachOError if the proper
length of data can't be read from |file|."""
bytes = CheckedRead(file, 4)
(uint32,) = struct.unpack(endian + 'I', bytes)
return uint32
def ReadMachHeader(file, endian):
"""Reads an entire |mach_header| structure (<mach-o/loader.h>) from the
file-like |file| object, treating it as having endianness specified by
|endian| (per the |struct| module), and returns a 7-tuple of its members
as numbers. Raises a MachOError if the proper length of data can't be read
from |file|."""
bytes = CheckedRead(file, 28)
magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
struct.unpack(endian + '7I', bytes)
return magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags
def ReadFatArch(file):
"""Reads an entire |fat_arch| structure (<mach-o/fat.h>) from the file-like
|file| object, treating it as having endianness specified by |endian|
(per the |struct| module), and returns a 5-tuple of its members as numbers.
Raises a MachOError if the proper length of data can't be read from
|file|."""
bytes = CheckedRead(file, 20)
cputype, cpusubtype, offset, size, align = struct.unpack('>5I', bytes)
return cputype, cpusubtype, offset, size, align
def WriteUInt32(file, uint32, endian):
"""Writes |uint32| as an unsinged 32-bit integer to the file-like |file|
object, treating it as having endianness specified by |endian| (per the
|struct| module)."""
bytes = struct.pack(endian + 'I', uint32)
assert len(bytes) == 4
file.write(bytes)
def HandleMachOFile(file, options, offset=0):
"""Seeks the file-like |file| object to |offset|, reads its |mach_header|,
and rewrites the header's |flags| field if appropriate. The header's
endianness is detected. Both 32-bit and 64-bit Mach-O headers are supported
(mach_header and mach_header_64). Raises MachOError if used on a header that
does not have a known magic number or is not of type MH_EXECUTE. The
MH_PIE and MH_NO_HEAP_EXECUTION bits are set or cleared in the |flags| field
according to |options| and written to |file| if any changes need to be made.
If already set or clear as specified by |options|, nothing is written."""
CheckedSeek(file, offset)
magic = ReadUInt32(file, '<')
if magic == MH_MAGIC or magic == MH_MAGIC_64:
endian = '<'
elif magic == MH_CIGAM or magic == MH_CIGAM_64:
endian = '>'
else:
raise MachOError('Mach-O file at offset %d has illusion of magic' % offset)
CheckedSeek(file, offset)
magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
ReadMachHeader(file, endian)
assert magic == MH_MAGIC or magic == MH_MAGIC_64
if filetype != MH_EXECUTE:
raise MachOError('Mach-O file at offset %d is type 0x%x, expected MH_EXECUTE' % \
(offset, filetype))
original_flags = flags
if options.no_heap_execution:
flags |= MH_NO_HEAP_EXECUTION
else:
flags &= ~MH_NO_HEAP_EXECUTION
if options.pie:
flags |= MH_PIE
else:
flags &= ~MH_PIE
if flags != original_flags:
CheckedSeek(file, offset + 24)
WriteUInt32(file, flags, endian)
def HandleFatFile(file, options, fat_offset=0):
"""Seeks the file-like |file| object to |offset| and loops over its
|fat_header| entries, calling HandleMachOFile for each."""
CheckedSeek(file, fat_offset)
magic = ReadUInt32(file, '>')
assert magic == FAT_MAGIC
nfat_arch = ReadUInt32(file, '>')
for index in range(0, nfat_arch):
cputype, cpusubtype, offset, size, align = ReadFatArch(file)
assert size >= 28
# HandleMachOFile will seek around. Come back here after calling it, in
# case it sought.
fat_arch_offset = file.tell()
HandleMachOFile(file, options, offset)
CheckedSeek(file, fat_arch_offset)
def main(me, args):
parser = optparse.OptionParser('%prog [options] <executable_path>')
parser.add_option('--executable-heap', action='store_false',
dest='no_heap_execution', default=True,
help='Clear the MH_NO_HEAP_EXECUTION bit')
parser.add_option('--no-pie', action='store_false',
dest='pie', default=True,
help='Clear the MH_PIE bit')
(options, loose_args) = parser.parse_args(args)
if len(loose_args) != 1:
parser.print_usage()
return 1
executable_path = loose_args[0]
executable_file = open(executable_path, 'rb+')
magic = ReadUInt32(executable_file, '<')
if magic == FAT_CIGAM:
# Check FAT_CIGAM and not FAT_MAGIC because the read was little-endian.
HandleFatFile(executable_file, options)
elif magic == MH_MAGIC or magic == MH_CIGAM or \
magic == MH_MAGIC_64 or magic == MH_CIGAM_64:
HandleMachOFile(executable_file, options)
else:
raise MachOError('%s is not a Mach-O or fat file' % executable_file)
executable_file.close()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[0], sys.argv[1:]))

View File

@@ -0,0 +1,15 @@
#!/bin/sh
# Copyright (c) 2011 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 is a small wrapper script around change_mach_o_flags.py allowing it to
# be invoked easily from Xcode. change_mach_o_flags.py expects its arguments
# on the command line, but Xcode puts its parameters in the environment.
set -e
exec "$(dirname "${0}")/change_mach_o_flags.py" \
"${@}" \
"${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"

View File

@@ -0,0 +1,36 @@
# -*- python -*-
# Crocodile config file for Chromium mac
{
# List of rules, applied in order
'rules' : [
# Specify inclusions before exclusions, since rules are in order.
# Don't include chromeos, linux, or windows specific files
{
'regexp' : '.*(_|/)(chromeos|linux|win|views)(\\.|_)',
'include' : 0,
},
# Don't include ChromeOS dirs
{
'regexp' : '.*/chromeos/',
'include' : 0,
},
# Groups
{
'regexp' : '.*_test_mac\\.',
'group' : 'test',
},
# Languages
{
'regexp' : '.*\\.m$',
'language' : 'ObjC',
},
{
'regexp' : '.*\\.mm$',
'language' : 'ObjC++',
},
],
}

View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Copyright (c) 2013 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.
# For app bundles built with ASan, copies the runtime lib
# (libclang_rt.asan_osx_dynamic.dylib), on which their executables depend, from
# the compiler installation path into the bundle and fixes the dylib's install
# name in the binary to be relative to @executable_path.
set -e
BINARY="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"
if [[ ! -f "$BINARY" ]]; then
# This is neither an .app bundle nor a standalone executable.
# Most certainly the script has been called for a data bundle.
exit 0
fi
BINARY_DIR="$(dirname "${BINARY}")"
# Find the link to the ASan runtime encoded in the binary.
BUILTIN_DYLIB_PATH=$(otool -L "${BINARY}" | \
sed -Ene 's/^[[:blank:]]+(.*libclang_rt\.asan_.*_dynamic\.dylib).*$/\1/p')
if [[ "${BUILTIN_DYLIB_PATH}" == *asan_iossim_dynamic* ]]; then
ASAN_DYLIB_NAME=libclang_rt.asan_iossim_dynamic.dylib
elif [[ "${BUILTIN_DYLIB_PATH}" == *asan_osx_dynamic* ]]; then
ASAN_DYLIB_NAME=libclang_rt.asan_osx_dynamic.dylib
fi
if [[ -z "${BUILTIN_DYLIB_PATH}" ]]; then
echo "${BINARY} does not depend on the ASan runtime library!" >&2
exit 1
fi
# TODO(glider): this doesn't work if we set CC and CXX to override the default
# Clang.
ASAN_DYLIB=$(find \
"${BUILT_PRODUCTS_DIR}/../../third_party/llvm-build/Release+Asserts/lib/clang/" \
-type f -path "*${ASAN_DYLIB_NAME}")
DYLIB_BASENAME=$(basename "${ASAN_DYLIB}")
if [[ "${DYLIB_BASENAME}" != "${ASAN_DYLIB_NAME}" ]]; then
echo "basename(${ASAN_DYLIB}) != ${ASAN_DYLIB_NAME}" >&2
exit 1
fi
# Check whether the directory containing the executable binary is named
# "MacOS". In this case we're building a full-fledged OSX app and will put
# the runtime into appname.app/Contents/Libraries/. Otherwise this is probably
# an iOS gtest app, and the ASan runtime is put next to the executable.
UPPER_DIR=$(dirname "${BINARY_DIR}")
if [ "${UPPER_DIR}" == "MacOS" ]; then
LIBRARIES_DIR="${UPPER_DIR}/Libraries"
mkdir -p "${LIBRARIES_DIR}"
NEW_LC_ID_DYLIB="@executable_path/../Libraries/${ASAN_DYLIB_NAME}"
else
LIBRARIES_DIR="${BINARY_DIR}"
NEW_LC_ID_DYLIB="@executable_path/${ASAN_DYLIB_NAME}"
fi
cp "${ASAN_DYLIB}" "${LIBRARIES_DIR}"
# Make LC_ID_DYLIB of the runtime copy point to its location.
install_name_tool \
-id "${NEW_LC_ID_DYLIB}" \
"${LIBRARIES_DIR}/${ASAN_DYLIB_NAME}"
# Fix the rpath to the runtime library recorded in the binary.
install_name_tool \
-change "${BUILTIN_DYLIB_PATH}" \
"${NEW_LC_ID_DYLIB}" \
"${BINARY}"

View File

@@ -0,0 +1,118 @@
#!/bin/bash
# Copyright (c) 2012 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.
# Copies a framework to its new home, "unversioning" it.
#
# Normally, frameworks are versioned bundles. The contents of a framework are
# stored in a versioned directory within the bundle, and symbolic links
# provide access to the actual code and resources. See
# http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
#
# The symbolic links usually found in frameworks create problems. Symbolic
# links are excluded from code signatures. That means that it's possible to
# remove or retarget a symbolic link within a framework without affecting the
# seal. In Chrome's case, the outer .app bundle contains a framework where
# all application code and resources live. In order for the signature on the
# .app to be meaningful, it encompasses the framework. Because framework
# resources are accessed through the framework's symbolic links, this
# arrangement results in a case where the resources can be altered without
# affecting the .app signature's validity.
#
# Indirection through symbolic links also carries a runtime performance
# penalty on open() operations, although open() typically completes so quickly
# that this is not considered a major performance problem.
#
# To resolve these problems, the frameworks that ship within Chrome's .app
# bundle are unversioned. Unversioning is simple: instead of using the
# original outer .framework directory as the framework that ships within the
# .app, the inner versioned directory is used. Instead of accessing bundled
# resources through symbolic links, they are accessed directly. In normal
# situations, the only hard-coded use of the versioned directory is by dyld,
# when loading the framework's code, but this is handled through a normal
# Mach-O load command, and it is easy to adjust the load command to point to
# the unversioned framework code rather than the versioned counterpart.
#
# The resulting framework bundles aren't strictly conforming, but they work
# as well as normal versioned framework bundles.
#
# An option to skip running install_name_tool is available. By passing -I as
# the first argument to this script, install_name_tool will be skipped. This
# is only suitable for copied frameworks that will not be linked against, or
# when install_name_tool will be run on any linker output when something is
# linked against the copied framework. This option exists to allow signed
# frameworks to pass through without subjecting them to any modifications that
# would break their signatures.
set -e
RUN_INSTALL_NAME_TOOL=1
if [ $# -eq 3 ] && [ "${1}" = "-I" ] ; then
shift
RUN_INSTALL_NAME_TOOL=
fi
if [ $# -ne 2 ] ; then
echo "usage: ${0} [-I] FRAMEWORK DESTINATION_DIR" >& 2
exit 1
fi
# FRAMEWORK should be a path to a versioned framework bundle, ending in
# .framework. DESTINATION_DIR is the directory that the unversioned framework
# bundle will be copied to.
FRAMEWORK="${1}"
DESTINATION_DIR="${2}"
FRAMEWORK_NAME="$(basename "${FRAMEWORK}")"
if [ "${FRAMEWORK_NAME: -10}" != ".framework" ] ; then
echo "${0}: ${FRAMEWORK_NAME} does not end in .framework" >& 2
exit 1
fi
FRAMEWORK_NAME_NOEXT="${FRAMEWORK_NAME:0:$((${#FRAMEWORK_NAME} - 10))}"
# Find the current version.
VERSIONS="${FRAMEWORK}/Versions"
CURRENT_VERSION_LINK="${VERSIONS}/Current"
CURRENT_VERSION_ID="$(readlink "${VERSIONS}/Current")"
CURRENT_VERSION="${VERSIONS}/${CURRENT_VERSION_ID}"
# Make sure that the framework's structure makes sense as a versioned bundle.
if [ ! -e "${CURRENT_VERSION}/${FRAMEWORK_NAME_NOEXT}" ] ; then
echo "${0}: ${FRAMEWORK_NAME} does not contain a dylib" >& 2
exit 1
fi
DESTINATION="${DESTINATION_DIR}/${FRAMEWORK_NAME}"
# Copy the versioned directory within the versioned framework to its
# destination location.
mkdir -p "${DESTINATION_DIR}"
rsync -acC --delete --exclude Headers --exclude PrivateHeaders \
--include '*.so' "${CURRENT_VERSION}/" "${DESTINATION}"
if [[ -n "${RUN_INSTALL_NAME_TOOL}" ]]; then
# Adjust the Mach-O LC_ID_DYLIB load command in the framework. This does not
# change the LC_LOAD_DYLIB load commands in anything that may have already
# linked against the framework. Not all frameworks will actually need this
# to be changed. Some frameworks may already be built with the proper
# LC_ID_DYLIB for use as an unversioned framework. Xcode users can do this
# by setting LD_DYLIB_INSTALL_NAME to
# $(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(WRAPPER_NAME)/$(PRODUCT_NAME)
# If invoking ld via gcc or g++, pass the desired path to -Wl,-install_name
# at link time.
FRAMEWORK_DYLIB="${DESTINATION}/${FRAMEWORK_NAME_NOEXT}"
LC_ID_DYLIB_OLD="$(otool -l "${FRAMEWORK_DYLIB}" |
grep -A10 "^ *cmd LC_ID_DYLIB$" |
grep -m1 "^ *name" |
sed -Ee 's/^ *name (.*) \(offset [0-9]+\)$/\1/')"
VERSION_PATH="/Versions/${CURRENT_VERSION_ID}/${FRAMEWORK_NAME_NOEXT}"
LC_ID_DYLIB_NEW="$(echo "${LC_ID_DYLIB_OLD}" |
sed -Ee "s%${VERSION_PATH}$%/${FRAMEWORK_NAME_NOEXT}%")"
if [ "${LC_ID_DYLIB_NEW}" != "${LC_ID_DYLIB_OLD}" ] ; then
install_name_tool -id "${LC_ID_DYLIB_NEW}" "${FRAMEWORK_DYLIB}"
fi
fi

View File

@@ -0,0 +1,19 @@
#!/bin/sh
# Copyright (c) 2012 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 script is a convenience to run GYP for /src/chrome/chrome_nibs.gyp
# with the Xcode generator (as you likely use ninja). Documentation:
# http://dev.chromium.org/developers/design-documents/mac-xib-files
set -e
RELSRC=$(dirname "$0")/../..
SRC=$(cd "$RELSRC" && pwd)
export PYTHONPATH="$PYTHONPATH:$SRC/build"
export GYP_GENERATORS=xcode
"$SRC/tools/gyp/gyp" -I"$SRC/build/common.gypi" "$SRC/chrome/chrome_nibs.gyp"
echo "You can now edit XIB files in Xcode using:"
echo " $SRC/chrome/chrome_nibs.xcodeproj"

116
engine/src/build/mac/find_sdk.py Executable file
View File

@@ -0,0 +1,116 @@
#!/usr/bin/env python3
#
# Copyright (c) 2012 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.
"""Prints the lowest locally available SDK version greater than or equal to a
given minimum sdk version to standard output.
Usage:
python find_sdk.py 10.6 # Ignores SDKs < 10.6
"""
import json
import os
import re
import subprocess
import sys
from optparse import OptionParser
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from pyutil.file_util import symlink
PREBUILTS = os.path.realpath(os.path.join(
os.path.dirname(__file__), os.pardir, os.pardir, 'flutter', 'prebuilts',
))
def parse_version(version_str):
"""'10.6' => [10, 6]"""
return [int(x) for x in re.findall(r'(\d+)', version_str)]
def run_command_with_retry(command, timeout=10, retries=3):
"""
Runs a command using subprocess.check_output with timeout and retry logic.
Args:
command: A list representing the command and its arguments.
timeout: The maximum time (in seconds) to wait for each command execution.
retries: The number of times to retry the command if it times out.
Returns:
The output of the command as a bytes object if successful, otherwise
raises a CalledProcessError.
"""
for attempt in range(1, retries + 1):
try:
result = subprocess.check_output(command, timeout=timeout)
return result.decode('utf-8').strip()
except subprocess.TimeoutExpired:
if attempt >= retries:
raise # Re-raise the TimeoutExpired error after all retries
def main():
parser = OptionParser()
parser.add_option("--print_sdk_path",
action="store_true", dest="print_sdk_path", default=False,
help="Additionaly print the path the SDK (appears first).")
parser.add_option("--as-gclient-hook",
action="store_true", dest="as_gclient_hook", default=False,
help="Whether the script is running as a gclient hook.")
parser.add_option("--symlink",
action="store", type="string", dest="symlink",
help="Whether to create a symlink in the buildroot to the SDK.")
(options, args) = parser.parse_args()
min_sdk_version = args[0]
# On CI, Xcode is not yet installed when gclient hooks are being run.
# This is because the version of Xcode that CI installs might depend on the
# contents of the repo, so the repo must be set up first, which includes
# running the gclient hooks. Instead, on CI, this script will be run during
# GN.
running_on_luci = os.environ.get('LUCI_CONTEXT') is not None
if running_on_luci and options.as_gclient_hook:
return 0
symlink_path = options.symlink
if not running_on_luci and symlink_path is None:
symlink_path = PREBUILTS
job = subprocess.Popen(['xcode-select', '-print-path'],
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out, err = job.communicate()
if job.returncode != 0:
sys.stderr.writelines([out, err])
raise Exception(('Error %d running xcode-select, you might have to run '
'|sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer| '
'if you are using Xcode 4.') % job.returncode)
# xcrun --sdk macosx --show-sdk-path
sdk_command = [
'xcrun',
'--sdk',
'macosx',
'--show-sdk-path',
]
sdk_output = run_command_with_retry(sdk_command, timeout=300)
if symlink_path:
sdks_path = os.path.join(symlink_path, 'SDKs')
symlink_target = os.path.join(sdks_path, os.path.basename(sdk_output))
symlink(sdk_output, symlink_target)
sdk_output = symlink_target
if not options.as_gclient_hook:
print(sdk_output)
return 0
if __name__ == '__main__':
if sys.platform != 'darwin':
raise Exception("This script only runs on Mac")
sys.exit((main()))

View File

@@ -0,0 +1,91 @@
#!/bin/bash
# Copyright (c) 2012 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.
# Usage: make_more_helpers.sh <directory_within_contents> <app_name>
#
# This script creates additional helper .app bundles for Chromium, based on
# the existing helper .app bundle, changing their Mach-O header's flags to
# enable and disable various features. Based on Chromium Helper.app, it will
# create Chromium Helper EH.app, which has the MH_NO_HEAP_EXECUTION bit
# cleared to support Chromium child processes that require an executable heap,
# and Chromium Helper NP.app, which has the MH_PIE bit cleared to support
# Chromium child processes that cannot tolerate ASLR.
#
# This script expects to be called from the chrome_exe target as a postbuild,
# and operates directly within the built-up browser app's versioned directory.
#
# Each helper is adjusted by giving it the proper bundle name, renaming the
# executable, adjusting several Info.plist keys, and changing the executable's
# Mach-O flags.
set -eu
make_helper() {
local containing_dir="${1}"
local app_name="${2}"
local feature="${3}"
local flags="${4}"
local helper_name="${app_name} Helper"
local helper_stem="${containing_dir}/${helper_name}"
local original_helper="${helper_stem}.app"
if [[ ! -d "${original_helper}" ]]; then
echo "${0}: error: ${original_helper} is a required directory" >& 2
exit 1
fi
local original_helper_exe="${original_helper}/Contents/MacOS/${helper_name}"
if [[ ! -f "${original_helper_exe}" ]]; then
echo "${0}: error: ${original_helper_exe} is a required file" >& 2
exit 1
fi
local feature_helper="${helper_stem} ${feature}.app"
rsync -acC --delete --include '*.so' "${original_helper}/" "${feature_helper}"
local helper_feature="${helper_name} ${feature}"
local helper_feature_exe="${feature_helper}/Contents/MacOS/${helper_feature}"
mv "${feature_helper}/Contents/MacOS/${helper_name}" "${helper_feature_exe}"
local change_flags="$(dirname "${0}")/change_mach_o_flags.py"
"${change_flags}" ${flags} "${helper_feature_exe}"
local feature_info="${feature_helper}/Contents/Info"
local feature_info_plist="${feature_info}.plist"
defaults write "${feature_info}" "CFBundleDisplayName" "${helper_feature}"
defaults write "${feature_info}" "CFBundleExecutable" "${helper_feature}"
cfbundleid="$(defaults read "${feature_info}" "CFBundleIdentifier")"
feature_cfbundleid="${cfbundleid}.${feature}"
defaults write "${feature_info}" "CFBundleIdentifier" "${feature_cfbundleid}"
cfbundlename="$(defaults read "${feature_info}" "CFBundleName")"
feature_cfbundlename="${cfbundlename} ${feature}"
defaults write "${feature_info}" "CFBundleName" "${feature_cfbundlename}"
# As usual, defaults might have put the plist into whatever format excites
# it, but Info.plists get converted back to the expected XML format.
plutil -convert xml1 "${feature_info_plist}"
# `defaults` also changes the file permissions, so make the file
# world-readable again.
chmod a+r "${feature_info_plist}"
}
if [[ ${#} -ne 2 ]]; then
echo "usage: ${0} <directory_within_contents> <app_name>" >& 2
exit 1
fi
DIRECTORY_WITHIN_CONTENTS="${1}"
APP_NAME="${2}"
CONTENTS_DIR="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}"
CONTAINING_DIR="${CONTENTS_DIR}/${DIRECTORY_WITHIN_CONTENTS}"
make_helper "${CONTAINING_DIR}" "${APP_NAME}" "EH" "--executable-heap"
make_helper "${CONTAINING_DIR}" "${APP_NAME}" "NP" "--no-pie"

View File

@@ -0,0 +1,62 @@
#!/bin/bash
# Copyright (c) 2008 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 is a handy wrapper script that figures out how to call the strip
# utility (strip_save_dsym in this case), if it even needs to be called at all,
# and then does it. This script should be called by a post-link phase in
# targets that might generate Mach-O executables, dynamic libraries, or
# loadable bundles.
#
# An example "Strip If Needed" build phase placed after "Link Binary With
# Libraries" would do:
# exec "${XCODEPROJ_DEPTH}/build/mac/strip_from_xcode"
if [ "${CONFIGURATION}" != "Release" ] ; then
# Only strip in release mode.
exit 0
fi
declare -a FLAGS
# MACH_O_TYPE is not set for a command-line tool, so check PRODUCT_TYPE too.
# Weird.
if [ "${MACH_O_TYPE}" = "mh_execute" ] || \
[ "${PRODUCT_TYPE}" = "com.apple.product-type.tool" ] ; then
# Strip everything (no special flags). No-op.
true
elif [ "${MACH_O_TYPE}" = "mh_dylib" ] || \
[ "${MACH_O_TYPE}" = "mh_bundle" ]; then
# Strip debugging symbols and local symbols
FLAGS[${#FLAGS[@]}]=-S
FLAGS[${#FLAGS[@]}]=-x
elif [ "${MACH_O_TYPE}" = "staticlib" ] ; then
# Don't strip static libraries.
exit 0
else
# Warn, but don't treat this as an error.
echo $0: warning: unrecognized MACH_O_TYPE ${MACH_O_TYPE}
exit 0
fi
if [ -n "${STRIPFLAGS}" ] ; then
# Pick up the standard STRIPFLAGS Xcode setting, used for "Additional Strip
# Flags".
for stripflag in "${STRIPFLAGS}" ; do
FLAGS[${#FLAGS[@]}]="${stripflag}"
done
fi
if [ -n "${CHROMIUM_STRIP_SAVE_FILE}" ] ; then
# An Xcode project can communicate a file listing symbols to saved in this
# environment variable by setting it as a build setting. This isn't a
# standard Xcode setting. It's used in preference to STRIPFLAGS to
# eliminate quoting ambiguity concerns.
FLAGS[${#FLAGS[@]}]=-s
FLAGS[${#FLAGS[@]}]="${CHROMIUM_STRIP_SAVE_FILE}"
fi
exec "$(dirname ${0})/strip_save_dsym" "${FLAGS[@]}" \
"${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"

View File

@@ -0,0 +1,337 @@
#!/usr/bin/env python3
# Copyright (c) 2011 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.
# Usage: strip_save_dsym <whatever-arguments-you-would-pass-to-strip>
#
# strip_save_dsym is a wrapper around the standard strip utility. Given an
# input Mach-O file, strip_save_dsym will save a copy of the file in a "fake"
# .dSYM bundle for debugging, and then call strip to strip the Mach-O file.
# Note that the .dSYM file is a "fake" in that it's not a self-contained
# .dSYM bundle, it just contains a copy of the original (unstripped) Mach-O
# file, and therefore contains references to object files on the filesystem.
# The generated .dSYM bundle is therefore unsuitable for debugging in the
# absence of these .o files.
#
# If a .dSYM already exists and has a newer timestamp than the Mach-O file,
# this utility does nothing. That allows strip_save_dsym to be run on a file
# that has already been stripped without trashing the .dSYM.
#
# Rationale: the "right" way to generate dSYM bundles, dsymutil, is incredibly
# slow. On the other hand, doing a file copy (which is really all that
# dsymutil does) is comparatively fast. Since we usually just want to strip
# a release-mode executable but still be able to debug it, and we don't care
# so much about generating a hermetic dSYM bundle, we'll prefer the file copy.
# If a real dSYM is ever needed, it's still possible to create one by running
# dsymutil and pointing it at the original Mach-O file inside the "fake"
# bundle, provided that the object files are available.
import errno
import os
import re
import shutil
import subprocess
import sys
import time
# Returns a list of architectures contained in a Mach-O file. The file can be
# a universal (fat) file, in which case there will be one list element for
# each contained architecture, or it can be a thin single-architecture Mach-O
# file, in which case the list will contain a single element identifying the
# architecture. On error, returns an empty list. Determines the architecture
# list by calling file.
def macho_archs(macho):
macho_types = ["executable",
"dynamically linked shared library",
"bundle"]
macho_types_re = "Mach-O (?:64-bit )?(?:" + "|".join(macho_types) + ")"
file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "--", macho],
stdout=subprocess.PIPE)
archs = []
type_line = file_cmd.stdout.readline()
type_match = re.match("^%s (.*)$" % macho_types_re, type_line)
if type_match:
archs.append(type_match.group(1))
return [type_match.group(1)]
else:
type_match = re.match("^Mach-O universal binary with (.*) architectures$",
type_line)
if type_match:
for i in range(0, int(type_match.group(1))):
arch_line = file_cmd.stdout.readline()
arch_match = re.match(
"^.* \(for architecture (.*)\):\t%s .*$" % macho_types_re,
arch_line)
if arch_match:
archs.append(arch_match.group(1))
if file_cmd.wait() != 0:
archs = []
if len(archs) == 0:
print("No architectures in %s" % macho, file=sys.stderr)
return archs
# Returns a dictionary mapping architectures contained in the file as returned
# by macho_archs to the LC_UUID load command for that architecture.
# Architectures with no LC_UUID load command are omitted from the dictionary.
# Determines the UUID value by calling otool.
def macho_uuids(macho):
uuids = {}
archs = macho_archs(macho)
if len(archs) == 0:
return uuids
for arch in archs:
if arch == "":
continue
otool_cmd = subprocess.Popen(["/usr/bin/otool", "-arch", arch, "-l", "-",
macho],
stdout=subprocess.PIPE)
# state 0 is when nothing UUID-related has been seen yet. State 1 is
# entered after a load command begins, but it may not be an LC_UUID load
# command. States 2, 3, and 4 are intermediate states while reading an
# LC_UUID command. State 5 is the terminal state for a successful LC_UUID
# read. State 6 is the error state.
state = 0
uuid = ""
for otool_line in otool_cmd.stdout:
if state == 0:
if re.match("^Load command .*$", otool_line):
state = 1
elif state == 1:
if re.match("^ cmd LC_UUID$", otool_line):
state = 2
else:
state = 0
elif state == 2:
if re.match("^ cmdsize 24$", otool_line):
state = 3
else:
state = 6
elif state == 3:
# The UUID display format changed in the version of otool shipping
# with the Xcode 3.2.2 prerelease. The new format is traditional:
# uuid 4D7135B2-9C56-C5F5-5F49-A994258E0955
# and with Xcode 3.2.6, then line is indented one more space:
# uuid 4D7135B2-9C56-C5F5-5F49-A994258E0955
# The old format, from cctools-750 and older's otool, breaks the UUID
# up into a sequence of bytes:
# uuid 0x4d 0x71 0x35 0xb2 0x9c 0x56 0xc5 0xf5
# 0x5f 0x49 0xa9 0x94 0x25 0x8e 0x09 0x55
new_uuid_match = re.match("^ {3,4}uuid (.{8}-.{4}-.{4}-.{4}-.{12})$",
otool_line)
if new_uuid_match:
uuid = new_uuid_match.group(1)
# Skip state 4, there is no second line to read.
state = 5
else:
old_uuid_match = re.match("^ uuid 0x(..) 0x(..) 0x(..) 0x(..) "
"0x(..) 0x(..) 0x(..) 0x(..)$",
otool_line)
if old_uuid_match:
state = 4
uuid = old_uuid_match.group(1) + old_uuid_match.group(2) + \
old_uuid_match.group(3) + old_uuid_match.group(4) + "-" + \
old_uuid_match.group(5) + old_uuid_match.group(6) + "-" + \
old_uuid_match.group(7) + old_uuid_match.group(8) + "-"
else:
state = 6
elif state == 4:
old_uuid_match = re.match("^ 0x(..) 0x(..) 0x(..) 0x(..) "
"0x(..) 0x(..) 0x(..) 0x(..)$",
otool_line)
if old_uuid_match:
state = 5
uuid += old_uuid_match.group(1) + old_uuid_match.group(2) + "-" + \
old_uuid_match.group(3) + old_uuid_match.group(4) + \
old_uuid_match.group(5) + old_uuid_match.group(6) + \
old_uuid_match.group(7) + old_uuid_match.group(8)
else:
state = 6
if otool_cmd.wait() != 0:
state = 6
if state == 5:
uuids[arch] = uuid.upper()
if len(uuids) == 0:
print("No UUIDs in %s" % macho, file=sys.stderr)
return uuids
# Given a path to a Mach-O file and possible information from the environment,
# determines the desired path to the .dSYM.
def dsym_path(macho):
# If building a bundle, the .dSYM should be placed next to the bundle. Use
# WRAPPER_NAME to make this determination. If called from xcodebuild,
# WRAPPER_NAME will be set to the name of the bundle.
dsym = ""
if "WRAPPER_NAME" in os.environ:
if "BUILT_PRODUCTS_DIR" in os.environ:
dsym = os.path.join(os.environ["BUILT_PRODUCTS_DIR"],
os.environ["WRAPPER_NAME"])
else:
dsym = os.environ["WRAPPER_NAME"]
else:
dsym = macho
dsym += ".dSYM"
return dsym
# Creates a fake .dSYM bundle at dsym for macho, a Mach-O image with the
# architectures and UUIDs specified by the uuids map.
def make_fake_dsym(macho, dsym):
uuids = macho_uuids(macho)
if len(uuids) == 0:
return False
dwarf_dir = os.path.join(dsym, "Contents", "Resources", "DWARF")
dwarf_file = os.path.join(dwarf_dir, os.path.basename(macho))
try:
os.makedirs(dwarf_dir)
except OSError as xxx_todo_changeme:
(err, error_string) = xxx_todo_changeme.args
if err != errno.EEXIST:
raise
shutil.copyfile(macho, dwarf_file)
# info_template is the same as what dsymutil would have written, with the
# addition of the fake_dsym key.
info_template = \
'''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.%(root_name)s</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>dSYM_UUID</key>
<dict>
%(uuid_dict)s </dict>
<key>fake_dsym</key>
<true/>
</dict>
</plist>
'''
root_name = os.path.basename(dsym)[:-5] # whatever.dSYM without .dSYM
uuid_dict = ""
for arch in sorted(uuids):
uuid_dict += "\t\t\t<key>" + arch + "</key>\n"\
"\t\t\t<string>" + uuids[arch] + "</string>\n"
info_dict = {
"root_name": root_name,
"uuid_dict": uuid_dict,
}
info_contents = info_template % info_dict
info_file = os.path.join(dsym, "Contents", "Info.plist")
info_fd = open(info_file, "w")
info_fd.write(info_contents)
info_fd.close()
return True
# For a Mach-O file, determines where the .dSYM bundle should be located. If
# the bundle does not exist or has a modification time older than the Mach-O
# file, calls make_fake_dsym to create a fake .dSYM bundle there, then strips
# the Mach-O file and sets the modification time on the .dSYM bundle and Mach-O
# file to be identical.
def strip_and_make_fake_dsym(macho):
dsym = dsym_path(macho)
macho_stat = os.stat(macho)
dsym_stat = None
try:
dsym_stat = os.stat(dsym)
except OSError as xxx_todo_changeme1:
(err, error_string) = xxx_todo_changeme1.args
if err != errno.ENOENT:
raise
if dsym_stat is None or dsym_stat.st_mtime < macho_stat.st_mtime:
# Make a .dSYM bundle
if not make_fake_dsym(macho, dsym):
return False
# Strip the Mach-O file
remove_dsym = True
try:
strip_cmdline = ['xcrun', 'strip'] + sys.argv[1:]
strip_cmd = subprocess.Popen(strip_cmdline)
if strip_cmd.wait() == 0:
remove_dsym = False
finally:
if remove_dsym:
shutil.rmtree(dsym)
# Update modification time on the Mach-O file and .dSYM bundle
now = time.time()
os.utime(macho, (now, now))
os.utime(dsym, (now, now))
return True
def main(argv=None):
if argv is None:
argv = sys.argv
# This only supports operating on one file at a time. Look at the arguments
# to strip to figure out what the source to be stripped is. Arguments are
# processed in the same way that strip does, although to reduce complexity,
# this doesn't do all of the same checking as strip. For example, strip
# has no -Z switch and would treat -Z on the command line as an error. For
# the purposes this is needed for, that's fine.
macho = None
process_switches = True
ignore_argument = False
for arg in argv[1:]:
if ignore_argument:
ignore_argument = False
continue
if process_switches:
if arg == "-":
process_switches = False
# strip has these switches accept an argument:
if arg in ["-s", "-R", "-d", "-o", "-arch"]:
ignore_argument = True
if arg[0] == "-":
continue
if macho is None:
macho = arg
else:
print("Too many things to strip", file=sys.stderr)
return 1
if macho is None:
print("Nothing to strip", file=sys.stderr)
return 1
if not strip_and_make_fake_dsym(macho):
return 1
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))

View File

@@ -0,0 +1,280 @@
#!/usr/bin/env python3
# Copyright (c) 2012 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.
#
# Xcode supports build variable substitutions and CPP; sadly, that doesn't work
# because:
#
# 1. Xcode wants to do the Info.plist work before it runs any build phases,
# this means if we were to generate a .h file for INFOPLIST_PREFIX_HEADER
# we'd have to put it in another target so it runs in time.
# 2. Xcode also doesn't check to see if the header being used as a prefix for
# the Info.plist has changed. So even if we updated it, it's only looking
# at the modtime of the info.plist to see if that's changed.
#
# So, we work around all of this by making a script build phase that will run
# during the app build, and simply update the info.plist in place. This way
# by the time the app target is done, the info.plist is correct.
#
import optparse
import os
from os import environ as env
import plistlib
import re
import subprocess
import sys
import tempfile
TOP = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
def _GetOutput(args):
"""Runs a subprocess and waits for termination. Returns (stdout, returncode)
of the process. stderr is attached to the parent."""
proc = subprocess.Popen(args, stdout=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
return (stdout, proc.returncode)
def _GetOutputNoError(args):
"""Similar to _GetOutput() but ignores stderr. If there's an error launching
the child (like file not found), the exception will be caught and (None, 1)
will be returned to mimic quiet failure."""
try:
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError:
return (None, 1)
(stdout, stderr) = proc.communicate()
return (stdout, proc.returncode)
def _RemoveKeys(plist, *keys):
"""Removes a varargs of keys from the plist."""
for key in keys:
try:
del plist[key]
except KeyError:
pass
def _AddVersionKeys(plist, version=None):
"""Adds the product version number into the plist. Returns True on success and
False on error. The error will be printed to stderr."""
if version:
match = re.match('\d+\.\d+\.(\d+\.\d+)$', version)
if not match:
print('Invalid version string specified: "%s"' % version, file=sys.stderr)
return False
full_version = match.group(0)
bundle_version = match.group(1)
else:
# Pull in the Chrome version number.
VERSION_TOOL = os.path.join(TOP, 'build/util/version.py')
VERSION_FILE = os.path.join(TOP, 'chrome/VERSION')
(stdout, retval1) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
'@MAJOR@.@MINOR@.@BUILD@.@PATCH@'])
full_version = stdout.rstrip()
(stdout, retval2) = _GetOutput([VERSION_TOOL, '-f', VERSION_FILE, '-t',
'@BUILD@.@PATCH@'])
bundle_version = stdout.rstrip()
# If either of the two version commands finished with non-zero returncode,
# report the error up.
if retval1 or retval2:
return False
# Add public version info so "Get Info" works.
plist['CFBundleShortVersionString'] = full_version
# Honor the 429496.72.95 limit. The maximum comes from splitting 2^32 - 1
# into 6, 2, 2 digits. The limitation was present in Tiger, but it could
# have been fixed in later OS release, but hasn't been tested (it's easy
# enough to find out with "lsregister -dump).
# http://lists.apple.com/archives/carbon-dev/2006/Jun/msg00139.html
# BUILD will always be an increasing value, so BUILD_PATH gives us something
# unique that meetings what LS wants.
plist['CFBundleVersion'] = bundle_version
# Return with no error.
return True
def _DoSCMKeys(plist, add_keys):
"""Adds the SCM information, visible in about:version, to property list. If
|add_keys| is True, it will insert the keys, otherwise it will remove them."""
scm_revision = None
if add_keys:
# Pull in the Chrome revision number.
VERSION_TOOL = os.path.join(TOP, 'build/util/version.py')
LASTCHANGE_FILE = os.path.join(TOP, 'build/util/LASTCHANGE')
(stdout, retval) = _GetOutput([VERSION_TOOL, '-f', LASTCHANGE_FILE, '-t',
'@LASTCHANGE@'])
if retval:
return False
scm_revision = stdout.rstrip()
# See if the operation failed.
_RemoveKeys(plist, 'SCMRevision')
if scm_revision != None:
plist['SCMRevision'] = scm_revision
elif add_keys:
print('Could not determine SCM revision. This may be OK.', file=sys.stderr)
return True
def _AddBreakpadKeys(plist, branding):
"""Adds the Breakpad keys. This must be called AFTER _AddVersionKeys() and
also requires the |branding| argument."""
plist['BreakpadReportInterval'] = '3600' # Deliberately a string.
plist['BreakpadProduct'] = '%s_Mac' % branding
plist['BreakpadProductDisplay'] = branding
plist['BreakpadVersion'] = plist['CFBundleShortVersionString']
# These are both deliberately strings and not boolean.
plist['BreakpadSendAndExit'] = 'YES'
plist['BreakpadSkipConfirm'] = 'YES'
def _RemoveBreakpadKeys(plist):
"""Removes any set Breakpad keys."""
_RemoveKeys(plist,
'BreakpadURL',
'BreakpadReportInterval',
'BreakpadProduct',
'BreakpadProductDisplay',
'BreakpadVersion',
'BreakpadSendAndExit',
'BreakpadSkipConfirm')
def _TagSuffixes():
# Keep this list sorted in the order that tag suffix components are to
# appear in a tag value. That is to say, it should be sorted per ASCII.
components = ('32bit', 'full')
assert tuple(sorted(components)) == components
components_len = len(components)
combinations = 1 << components_len
tag_suffixes = []
for combination in range(0, combinations):
tag_suffix = ''
for component_index in range(0, components_len):
if combination & (1 << component_index):
tag_suffix += '-' + components[component_index]
tag_suffixes.append(tag_suffix)
return tag_suffixes
def _AddKeystoneKeys(plist, bundle_identifier):
"""Adds the Keystone keys. This must be called AFTER _AddVersionKeys() and
also requires the |bundle_identifier| argument (com.example.product)."""
plist['KSVersion'] = plist['CFBundleShortVersionString']
plist['KSProductID'] = bundle_identifier
plist['KSUpdateURL'] = 'https://tools.google.com/service/update2'
_RemoveKeys(plist, 'KSChannelID')
for tag_suffix in _TagSuffixes():
if tag_suffix:
plist['KSChannelID' + tag_suffix] = tag_suffix
def _RemoveKeystoneKeys(plist):
"""Removes any set Keystone keys."""
_RemoveKeys(plist,
'KSVersion',
'KSProductID',
'KSUpdateURL')
tag_keys = []
for tag_suffix in _TagSuffixes():
tag_keys.append('KSChannelID' + tag_suffix)
_RemoveKeys(plist, *tag_keys)
def Main(argv):
parser = optparse.OptionParser('%prog [options]')
parser.add_option('--breakpad', dest='use_breakpad', action='store',
type='int', default=False, help='Enable Breakpad [1 or 0]')
parser.add_option('--breakpad_uploads', dest='breakpad_uploads',
action='store', type='int', default=False,
help='Enable Breakpad\'s uploading of crash dumps [1 or 0]')
parser.add_option('--keystone', dest='use_keystone', action='store',
type='int', default=False, help='Enable Keystone [1 or 0]')
parser.add_option('--scm', dest='add_scm_info', action='store', type='int',
default=True, help='Add SCM metadata [1 or 0]')
parser.add_option('--branding', dest='branding', action='store',
type='string', default=None, help='The branding of the binary')
parser.add_option('--bundle_id', dest='bundle_identifier',
action='store', type='string', default=None,
help='The bundle id of the binary')
parser.add_option('--version', dest='version', action='store', type='string',
default=None, help='The version string [major.minor.build.patch]')
(options, args) = parser.parse_args(argv)
if len(args) > 0:
print(parser.get_usage(), file=sys.stderr)
return 1
# Read the plist into its parsed format.
DEST_INFO_PLIST = os.path.join(env['TARGET_BUILD_DIR'], env['INFOPLIST_PATH'])
plist = plistlib.readPlist(DEST_INFO_PLIST)
# Insert the product version.
if not _AddVersionKeys(plist, version=options.version):
return 2
# Add Breakpad if configured to do so.
if options.use_breakpad:
if options.branding is None:
print('Use of Breakpad requires branding.', file=sys.stderr)
return 1
_AddBreakpadKeys(plist, options.branding)
if options.breakpad_uploads:
plist['BreakpadURL'] = 'https://clients2.google.com/cr/report'
else:
# This allows crash dumping to a file without uploading the
# dump, for testing purposes. Breakpad does not recognise
# "none" as a special value, but this does stop crash dump
# uploading from happening. We need to specify something
# because if "BreakpadURL" is not present, Breakpad will not
# register its crash handler and no crash dumping will occur.
plist['BreakpadURL'] = 'none'
else:
_RemoveBreakpadKeys(plist)
# Only add Keystone in Release builds.
if options.use_keystone and env['CONFIGURATION'] == 'Release':
if options.bundle_identifier is None:
print('Use of Keystone requires the bundle id.', file=sys.stderr)
return 1
_AddKeystoneKeys(plist, options.bundle_identifier)
else:
_RemoveKeystoneKeys(plist)
# Adds or removes any SCM keys.
if not _DoSCMKeys(plist, options.add_scm_info):
return 3
# Now that all keys have been mutated, rewrite the file.
temp_info_plist = tempfile.NamedTemporaryFile()
plistlib.writePlist(plist, temp_info_plist.name)
# Info.plist will work perfectly well in any plist format, but traditionally
# applications use xml1 for this, so convert it to ensure that it's valid.
proc = subprocess.Popen(['plutil', '-convert', 'xml1', '-o', DEST_INFO_PLIST,
temp_info_plist.name])
proc.wait()
return proc.returncode
if __name__ == '__main__':
sys.exit(Main(sys.argv[1:]))

View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Copyright (c) 2011 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 script makes sure that no __OBJC,__image_info section appears in the
# executable file built by the Xcode target that runs the script. If such a
# section appears, the script prints an error message and exits nonzero.
#
# Why is this important?
#
# On 10.5, there's a bug in CFBundlePreflightExecutable that causes it to
# crash when operating in an executable that has not loaded at its default
# address (that is, when it's a position-independent executable with the
# MH_PIE bit set in its mach_header) and the executable has an
# __OBJC,__image_info section. See http://crbug.com/88697.
#
# Chrome's main executables don't use any Objective-C at all, and don't need
# to carry this section around. Not linking them as Objective-C when they
# don't need it anyway saves about 4kB in the linked executable, although most
# of that 4kB is just filled with zeroes.
#
# This script makes sure that nobody goofs and accidentally introduces these
# sections into the main executables.
set -eu
executable="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"
if xcrun otool -arch i386 -o "${executable}" | grep -q '^Contents.*section$'; \
then
echo "${0}: ${executable} has an __OBJC,__image_info section" 2>&1
exit 1
fi
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
echo "${0}: otool failed" 2>&1
exit 1
fi
exit 0

View File

@@ -0,0 +1,7 @@
// Copyright (c) 2011 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.
// Precompiled header generator for Windows builds. No include is needed
// in this file as the PCH include is forced via the "Forced Include File"
// flag in the projects generated by GYP.

View File

@@ -0,0 +1,109 @@
// Copyright (c) 2012 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.
// Precompiled header for Chromium project on Windows, not used by
// other build configurations. Using precompiled headers speeds the
// build up significantly, around 1/4th on VS 2010 on an HP Z600 with 12
// GB of memory.
//
// Numeric comments beside includes are the number of times they were
// included under src/chrome/browser on 2011/8/20, which was used as a
// baseline for deciding what to include in the PCH. Includes without
// a numeric comment are generally included at least 5 times. It may
// be possible to tweak the speed of the build by commenting out or
// removing some of the less frequently used headers.
#if defined(BUILD_PRECOMPILE_H_)
#error You shouldn't include the precompiled header file more than once.
#endif
#define BUILD_PRECOMPILE_H_
#define _USE_MATH_DEFINES
// The Windows header needs to come before almost all the other
// Windows-specific headers.
#include <Windows.h>
#include <dwmapi.h>
#include <shellapi.h>
#include <wtypes.h> // 2
// Defines in atlbase.h cause conflicts; if we could figure out how
// this family of headers can be included in the PCH, it might speed
// up the build as several of them are used frequently.
/*
#include <atlbase.h>
#include <atlapp.h>
#include <atlcom.h>
#include <atlcrack.h> // 2
#include <atlctrls.h> // 2
#include <atlmisc.h> // 2
#include <atlsafe.h> // 1
#include <atltheme.h> // 1
#include <atlwin.h> // 2
*/
// Objbase.h and other files that rely on it bring in [ #define
// interface struct ] which can cause problems in a multi-platform
// build like Chrome's. #undef-ing it does not work as there are
// currently 118 targets that break if we do this, so leaving out of
// the precompiled header for now.
//#include <commctrl.h> // 2
//#include <commdlg.h> // 3
//#include <cryptuiapi.h> // 2
//#include <Objbase.h> // 2
//#include <objidl.h> // 1
//#include <ole2.h> // 1
//#include <oleacc.h> // 2
//#include <oleauto.h> // 1
//#include <oleidl.h> // 1
//#include <propkey.h> // 2
//#include <propvarutil.h> // 2
//#include <pstore.h> // 2
//#include <shlguid.h> // 1
//#include <shlwapi.h> // 1
//#include <shobjidl.h> // 4
//#include <urlhist.h> // 2
// Caused other conflicts in addition to the 'interface' issue above.
// #include <shlobj.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h> // 4
#include <math.h>
#include <memory.h> // 1
#include <signal.h>
#include <stdarg.h> // 1
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> // 4
#include <algorithm>
#include <bitset> // 3
#include <cmath>
#include <cstddef>
#include <cstdio> // 3
#include <cstdlib> // 2
#include <cstring>
#include <deque>
#include <fstream> // 3
#include <functional>
#include <iomanip> // 2
#include <iosfwd> // 2
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <numeric> // 2
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

Some files were not shown because too many files have changed in this diff Show More