Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: tools/build.py

Issue 2996903002: [infra] Translate _sources.gypi files to _sources.gni files (Closed)
Patch Set: Fix script Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android_link.py ('k') | tools/gypi_to_gn.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/build.py
diff --git a/tools/build.py b/tools/build.py
index 0c780f370767c205db3f13a90d9dc04fe56cf2bb..df5c045ba18c82db49c83c8b9d7de185b8a73ca2 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -3,614 +3,12 @@
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-#
-
-import optparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-import time
-import utils
-
-HOST_OS = utils.GuessOS()
-HOST_ARCH = utils.GuessArchitecture()
-HOST_CPUS = utils.GuessCpus()
-SCRIPT_DIR = os.path.dirname(sys.argv[0])
-DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party')
-
-arm_cc_error = """
-Couldn't find the arm cross compiler.
-To make sure that you have the arm cross compilation tools installed, run:
-
-$ wget http://src.chromium.org/chrome/trunk/src/build/install-build-deps.sh
-OR
-$ svn co http://src.chromium.org/chrome/trunk/src/build; cd build
-Then,
-$ chmod u+x install-build-deps.sh
-$ ./install-build-deps.sh --arm --no-chromeos-fonts
-"""
-DEFAULT_ARM_CROSS_COMPILER_PATH = '/usr/bin'
-
-usage = """\
-usage: %%prog [options] [targets]
-
-This script runs 'make' in the *current* directory. So, run it from
-the Dart repo root,
-
- %s ,
-
-unless you really intend to use a non-default Makefile.""" % DART_ROOT
-
-DART_USE_GYP = "DART_USE_GYP"
-
-
-def use_gyp():
- return DART_USE_GYP in os.environ
-
-
-def BuildOptions():
- result = optparse.OptionParser(usage=usage)
- result.add_option("-m", "--mode",
- help='Build variants (comma-separated).',
- metavar='[all,debug,release,product]',
- default='debug')
- result.add_option("-v", "--verbose",
- help='Verbose output.',
- default=False, action="store_true")
- result.add_option("-a", "--arch",
- help='Target architectures (comma-separated).',
- metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,'
- 'simarm64,arm64,simdbc,armsimdbc]',
- default=utils.GuessArchitecture())
- result.add_option("--os",
- help='Target OSs (comma-separated).',
- metavar='[all,host,android]',
- default='host')
- result.add_option("-t", "--toolchain",
- help='Cross-compiler toolchain path',
- default=None)
- result.add_option("-j",
- help='The number of parallel jobs to run.',
- metavar=HOST_CPUS,
- default=str(HOST_CPUS))
- (vs_directory, vs_executable) = utils.GuessVisualStudioPath()
- result.add_option("--devenv",
- help='Path containing devenv.com on Windows',
- default=vs_directory)
- result.add_option("--executable",
- help='Name of the devenv.com/msbuild executable on Windows (varies for '
- 'different versions of Visual Studio)',
- default=vs_executable)
- result.add_option("--gyp",
- help='Build with gyp.',
- default=use_gyp(),
- action='store_true')
- return result
-
-
-def ProcessOsOption(os_name):
- if os_name == 'host':
- return HOST_OS
- return os_name
-
-
-def ProcessOptions(options, args):
- if options.arch == 'all':
- options.arch = 'ia32,x64,simarm,simarm64,simdbc64'
- if options.mode == 'all':
- options.mode = 'debug,release,product'
- if options.os == 'all':
- options.os = 'host,android'
- options.mode = options.mode.split(',')
- options.arch = options.arch.split(',')
- options.os = options.os.split(',')
- if not options.gyp and options.toolchain != None:
- print "The --toolchain flag is only supported by the gyp build."
- print "When using the GN build, set the toolchain and sysroot using gn.py."
- return False
- for mode in options.mode:
- if not mode in ['debug', 'release', 'product']:
- print "Unknown mode %s" % mode
- return False
- for arch in options.arch:
- archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
- 'simarmv5te', 'armv5te', 'simarm64', 'arm64',
- 'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']
- if not arch in archs:
- print "Unknown arch %s" % arch
- return False
- options.os = [ProcessOsOption(os_name) for os_name in options.os]
- for os_name in options.os:
- if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
- print "Unknown os %s" % os_name
- return False
- if os_name != HOST_OS:
- if os_name != 'android':
- print "Unsupported target os %s" % os_name
- return False
- if not HOST_OS in ['linux', 'macos']:
- print ("Cross-compilation to %s is not supported on host os %s."
- % (os_name, HOST_OS))
- return False
- if not arch in ['ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64',
- 'simdbc', 'simdbc64']:
- print ("Cross-compilation to %s is not supported for architecture %s."
- % (os_name, arch))
- return False
- # We have not yet tweaked the v8 dart build to work with the Android
- # NDK/SDK, so don't try to build it.
- if not args:
- print "For android builds you must specify a target, such as 'runtime'."
- return False
- return True
-
-
-def GetToolchainPrefix(target_os, arch, options):
- if options.toolchain != None:
- return options.toolchain
-
- if target_os == 'android':
- android_toolchain = GetAndroidToolchainDir(HOST_OS, arch)
- if arch == 'arm' or arch == 'simdbc':
- return os.path.join(android_toolchain, 'arm-linux-androideabi')
- if arch == 'arm64' or arch == 'simdbc64':
- return os.path.join(android_toolchain, 'aarch64-linux-android')
- if arch == 'ia32':
- return os.path.join(android_toolchain, 'i686-linux-android')
- if arch == 'x64':
- return os.path.join(android_toolchain, 'x86_64-linux-android')
-
- # If no cross compiler is specified, only try to figure one out on Linux.
- if not HOST_OS in ['linux']:
- raise Exception('Unless --toolchain is used cross-building is only '
- 'supported on Linux.')
-
- # For ARM Linux, by default use the Linux distribution's cross-compiler.
- if arch == 'arm' or arch == 'armsimdbc':
- # To use a non-hf compiler, specify on the command line with --toolchain.
- return (DEFAULT_ARM_CROSS_COMPILER_PATH + "/arm-linux-gnueabihf")
- if arch == 'arm64':
- return (DEFAULT_ARM_CROSS_COMPILER_PATH + "/aarch64-linux-gnu")
-
- return None
-
-
-def SetTools(arch, target_os, options):
- toolsOverride = None
-
- toolchainprefix = GetToolchainPrefix(target_os, arch, options)
-
- # Override the Android toolchain's linker to handle some complexity in the
- # linker arguments that gyp has trouble with.
- linker = ""
- if target_os == 'android':
- linker = os.path.join(DART_ROOT, 'tools', 'android_link.py')
- elif toolchainprefix:
- linker = toolchainprefix + "-g++"
-
- if toolchainprefix:
- toolsOverride = {
- "CC.target" : toolchainprefix + "-gcc",
- "CXX.target" : toolchainprefix + "-g++",
- "AR.target" : toolchainprefix + "-ar",
- "LINK.target": linker,
- "NM.target" : toolchainprefix + "-nm",
- }
- return toolsOverride
-
-
-def CheckDirExists(path, docstring):
- if not os.path.isdir(path):
- raise Exception('Could not find %s directory %s'
- % (docstring, path))
-
-
-def GetAndroidToolchainDir(host_os, target_arch):
- global THIRD_PARTY_ROOT
- if host_os not in ['linux']:
- raise Exception('Unsupported host os %s' % host_os)
- if target_arch not in ['ia32', 'x64', 'arm', 'arm64', 'simdbc', 'simdbc64']:
- raise Exception('Unsupported target architecture %s' % target_arch)
-
- # Set up path to the Android NDK.
- CheckDirExists(THIRD_PARTY_ROOT, 'third party tools')
- android_tools = os.path.join(THIRD_PARTY_ROOT, 'android_tools')
- CheckDirExists(android_tools, 'Android tools')
- android_ndk_root = os.path.join(android_tools, 'ndk')
- CheckDirExists(android_ndk_root, 'Android NDK')
-
- # Set up the directory of the Android NDK cross-compiler toolchain.
- toolchain_arch = 'arm-linux-androideabi-4.9'
- if target_arch == 'arm64' or target_arch == 'simdbc64':
- toolchain_arch = 'aarch64-linux-android-4.9'
- if target_arch == 'ia32':
- toolchain_arch = 'x86-4.9'
- if target_arch == 'x64':
- toolchain_arch = 'x86_64-4.9'
- toolchain_dir = 'linux-x86_64'
- android_toolchain = os.path.join(android_ndk_root,
- 'toolchains', toolchain_arch,
- 'prebuilt', toolchain_dir, 'bin')
- CheckDirExists(android_toolchain, 'Android toolchain')
-
- return android_toolchain
-
-
-def Execute(args):
- process = subprocess.Popen(args)
- process.wait()
- if process.returncode != 0:
- raise Exception(args[0] + " failed")
-
-
-def CurrentDirectoryBaseName():
- """Returns the name of the current directory"""
- return os.path.relpath(os.curdir, start=os.pardir)
-
-def FilterEmptyXcodebuildSections(process):
- """
- Filter output from xcodebuild so empty sections are less verbose.
-
- The output from xcodebuild looks like this:
-
-Build settings from command line:
- SYMROOT = .../xcodebuild
-
-=== BUILD TARGET samples OF PROJECT dart WITH CONFIGURATION ...
-
-Check dependencies
-
-=== BUILD AGGREGATE TARGET upload_sdk OF PROJECT dart WITH CONFIGURATION ...
-
-Check dependencies
-
-PhaseScriptExecution "Action \"upload_sdk_py\"" xcodebuild/dart.build/...
- cd ...
- /bin/sh -c .../xcodebuild/dart.build/ReleaseIA32/upload_sdk.build/...
-
-
-** BUILD SUCCEEDED **
-
- """
-
- def is_empty_chunk(input):
- empty_chunk = ['', 'Check dependencies', '']
- return not input or (len(input) == 4 and input[1:] == empty_chunk)
-
- def unbuffered(callable):
- # Use iter to disable buffering in for-in.
- return iter(callable, '')
-
- section = None
- chunk = []
- # Is stdout a terminal which supports colors?
- is_fancy_tty = False
- clr_eol = None
- if sys.stdout.isatty():
- term = os.getenv('TERM', 'dumb')
- # The capability "clr_eol" means clear the line from cursor to end
- # of line. See man pages for tput and terminfo.
- try:
- with open('/dev/null', 'a') as dev_null:
- clr_eol = subprocess.check_output(['tput', '-T' + term, 'el'],
- stderr=dev_null)
- if clr_eol:
- is_fancy_tty = True
- except subprocess.CalledProcessError:
- is_fancy_tty = False
- except AttributeError:
- is_fancy_tty = False
- pattern = re.compile(r'=== BUILD.* TARGET (.*) OF PROJECT (.*) WITH ' +
- r'CONFIGURATION (.*) ===')
- has_interesting_info = False
- for line in unbuffered(process.stdout.readline):
- line = line.rstrip()
- if line.startswith('=== BUILD ') or line.startswith('** BUILD '):
- has_interesting_info = False
- section = line
- if is_fancy_tty:
- match = re.match(pattern, section)
- if match:
- section = '%s/%s/%s' % (
- match.group(3), match.group(2), match.group(1))
- # Truncate to avoid extending beyond 80 columns.
- section = section[:80]
- # If stdout is a terminal, emit "progress" information. The
- # progress information is the first line of the current chunk.
- # After printing the line, move the cursor back to the
- # beginning of the line. This has two effects: First, if the
- # chunk isn't empty, the first line will be overwritten
- # (avoiding duplication). Second, the next segment line will
- # overwrite it too avoid long scrollback. clr_eol ensures
- # that there is no trailing garbage when a shorter line
- # overwrites a longer line.
- print '%s%s\r' % (clr_eol, section),
- chunk = []
- if not section or has_interesting_info:
- print line
- else:
- length = len(chunk)
- if length == 2 and line != 'Check dependencies':
- has_interesting_info = True
- elif (length == 1 or length == 3) and line:
- has_interesting_info = True
- elif length > 3:
- has_interesting_info = True
- if has_interesting_info:
- print '\n'.join(chunk)
- chunk = []
- else:
- chunk.append(line)
- if not is_empty_chunk(chunk):
- print '\n'.join(chunk)
-
-
-def NotifyBuildDone(build_config, success, start):
- if not success:
- print "BUILD FAILED"
-
- sys.stdout.flush()
-
- # Display a notification if build time exceeded DART_BUILD_NOTIFICATION_DELAY.
- notification_delay = float(
- os.getenv('DART_BUILD_NOTIFICATION_DELAY', sys.float_info.max))
- if (time.time() - start) < notification_delay:
- return
-
- if success:
- message = 'Build succeeded.'
- else:
- message = 'Build failed.'
- title = build_config
-
- command = None
- if HOST_OS == 'macos':
- # Use AppleScript to display a UI non-modal notification.
- script = 'display notification "%s" with title "%s" sound name "Glass"' % (
- message, title)
- command = "osascript -e '%s' &" % script
- elif HOST_OS == 'linux':
- if success:
- icon = 'dialog-information'
- else:
- icon = 'dialog-error'
- command = "notify-send -i '%s' '%s' '%s' &" % (icon, message, title)
- elif HOST_OS == 'win32':
- if success:
- icon = 'info'
- else:
- icon = 'error'
- command = ("powershell -command \""
- "[reflection.assembly]::loadwithpartialname('System.Windows.Forms')"
- "| Out-Null;"
- "[reflection.assembly]::loadwithpartialname('System.Drawing')"
- "| Out-Null;"
- "$n = new-object system.windows.forms.notifyicon;"
- "$n.icon = [system.drawing.systemicons]::information;"
- "$n.visible = $true;"
- "$n.showballoontip(%d, '%s', '%s', "
- "[system.windows.forms.tooltipicon]::%s);\"") % (
- 5000, # Notification stays on for this many milliseconds
- message, title, icon)
-
- if command:
- # Ignore return code, if this command fails, it doesn't matter.
- os.system(command)
-
-
-def RunGN(target_os, mode, arch):
- gn_os = 'host' if target_os == HOST_OS else target_os
- gn_command = [
- 'python',
- os.path.join(DART_ROOT, 'tools', 'gn.py'),
- '-m', mode,
- '-a', arch,
- '--os', gn_os,
- '-v',
- ]
- process = subprocess.Popen(gn_command)
- process.wait()
- if process.returncode != 0:
- print ("Tried to run GN, but it failed. Try running it manually: \n\t$ " +
- ' '.join(gn_command))
-
-
-def ShouldRunGN(out_dir):
- return (not os.path.exists(out_dir) or
- not os.path.isfile(os.path.join(out_dir, 'args.gn')))
-
-
-def UseGoma(out_dir):
- args_gn = os.path.join(out_dir, 'args.gn')
- return 'use_goma = true' in open(args_gn, 'r').read()
-
-
-# Try to start goma, but don't bail out if we can't. Instead print an error
-# message, and let the build fail with its own error messages as well.
-def EnsureGomaStarted(out_dir):
- args_gn_path = os.path.join(out_dir, 'args.gn')
- goma_dir = None
- with open(args_gn_path, 'r') as fp:
- for line in fp:
- if 'goma_dir' in line:
- words = line.split()
- goma_dir = words[2][1:-1] # goma_dir = "/path/to/goma"
- if not goma_dir:
- print 'Could not find goma for ' + out_dir
- return False
- if not os.path.exists(goma_dir) or not os.path.isdir(goma_dir):
- print 'Could not find goma at ' + goma_dir
- return False
- goma_ctl = os.path.join(goma_dir, 'goma_ctl.py')
- goma_ctl_command = [
- 'python',
- goma_ctl,
- 'ensure_start',
- ]
- process = subprocess.Popen(goma_ctl_command)
- process.wait()
- if process.returncode != 0:
- print ("Tried to run goma_ctl.py, but it failed. Try running it manually: "
- + "\n\t" + ' '.join(goma_ctl_command))
- return False
- return True
-
-
-
-def BuildNinjaCommand(options, target, target_os, mode, arch):
- out_dir = utils.GetBuildRoot(HOST_OS, mode, arch, target_os)
- if ShouldRunGN(out_dir):
- RunGN(target_os, mode, arch)
- command = ['ninja', '-C', out_dir]
- if options.verbose:
- command += ['-v']
- if UseGoma(out_dir):
- if EnsureGomaStarted(out_dir):
- command += ['-j1000']
- else:
- # If we couldn't ensure that goma is started, let the build start, but
- # slowly so we can see any helpful error messages that pop out.
- command += ['-j1']
- command += [target]
- return command
-
-
-filter_xcodebuild_output = False
-def BuildOneConfig(options, target, target_os, mode, arch):
- global filter_xcodebuild_output
- start_time = time.time()
- args = []
- build_config = utils.GetBuildConf(mode, arch, target_os)
- if not options.gyp:
- args = BuildNinjaCommand(options, target, target_os, mode, arch)
- else:
- os.environ['DART_BUILD_MODE'] = mode
- if HOST_OS == 'macos':
- filter_xcodebuild_output = True
- project_file = 'dart.xcodeproj'
- if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
- project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName()
- if target == 'all':
- target = 'All'
- args = ['xcodebuild',
- '-project',
- project_file,
- '-target',
- target,
- '-configuration',
- build_config,
- 'SYMROOT=%s' % os.path.abspath('xcodebuild')
- ]
- elif HOST_OS == 'win32':
- project_file = 'dart.sln'
- if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
- project_file = 'dart-%s.sln' % CurrentDirectoryBaseName()
- # Select a platform suffix to pass to devenv.
- if arch == 'ia32':
- platform_suffix = 'Win32'
- elif arch == 'x64':
- platform_suffix = 'x64'
- else:
- print 'Unsupported arch for MSVC build: %s' % arch
- return 1
- config_name = '%s|%s' % (build_config, platform_suffix)
- if target == 'all':
- args = [options.devenv + os.sep + options.executable,
- '/build',
- config_name,
- project_file
- ]
- else:
- args = [options.devenv + os.sep + options.executable,
- '/build',
- config_name,
- '/project',
- target,
- project_file
- ]
- else:
- make = 'make'
- if HOST_OS == 'freebsd':
- make = 'gmake'
- # work around lack of flock
- os.environ['LINK'] = '$(CXX)'
- args = [make,
- '-j',
- options.j,
- 'BUILDTYPE=' + build_config,
- ]
- if target_os != HOST_OS:
- args += ['builddir_name=' + utils.GetBuildDir(HOST_OS)]
- if options.verbose:
- args += ['V=1']
-
- args += [target]
-
- toolsOverride = None
- if override_tools:
- toolsOverride = SetTools(arch, target_os, options)
- if toolsOverride:
- for k, v in toolsOverride.iteritems():
- args.append( k + "=" + v)
- if options.verbose:
- print k + " = " + v
- if not os.path.isfile(toolsOverride['CC.target']):
- if arch == 'arm':
- print arm_cc_error
- else:
- print "Couldn't find compiler: %s" % toolsOverride['CC.target']
- return 1
-
- print ' '.join(args)
- process = None
- if filter_xcodebuild_output:
- process = subprocess.Popen(args,
- stdin=None,
- bufsize=1, # Line buffered.
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- FilterEmptyXcodebuildSections(process)
- else:
- process = subprocess.Popen(args, stdin=None)
- process.wait()
- if process.returncode != 0:
- NotifyBuildDone(build_config, success=False, start=start_time)
- return 1
- else:
- NotifyBuildDone(build_config, success=True, start=start_time)
-
- return 0
-
-
-def Main():
- utils.ConfigureJava()
- # Parse the options.
- parser = BuildOptions()
- (options, args) = parser.parse_args()
- if not ProcessOptions(options, args):
- parser.print_help()
- return 1
- # Determine which targets to build. By default we build the "all" target.
- if len(args) == 0:
- targets = ['all']
- else:
- targets = args
-
- # Build all targets for each requested configuration.
- for target in targets:
- for target_os in options.os:
- for mode in options.mode:
- for arch in options.arch:
- if BuildOneConfig(options, target, target_os,
- mode, arch) != 0:
- return 1
-
- return 0
+# This script simply forwards to tools/ninja.py. It is retained simply to avoid
+# breaking various workflows.
+import ninja
+import sys
if __name__ == '__main__':
- sys.exit(Main())
+ sys.exit(ninja.Main())
« no previous file with comments | « tools/android_link.py ('k') | tools/gypi_to_gn.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698