128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#!/usr/bin/env python 228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# Copyright (C) 2010 Google Inc. All rights reserved. 328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# 428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# Redistribution and use in source and binary forms, with or without 528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# modification, are permitted provided that the following conditions are 628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# met: 728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# 828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# * Redistributions of source code must retain the above copyright 928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# notice, this list of conditions and the following disclaimer. 1028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# * Redistributions in binary form must reproduce the above 1128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# copyright notice, this list of conditions and the following disclaimer 1228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# in the documentation and/or other materials provided with the 1328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# distribution. 1428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# * Neither the name of Google Inc. nor the names of its 1528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# contributors may be used to endorse or promote products derived from 1628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# this software without specific prior written permission. 1728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# 1828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 3028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu"""Wrapper objects for WebKit-specific utility routines.""" 3128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 3228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# FIXME: This file needs to be unified with common/checkout/scm.py and 3328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# common/config/ports.py . 3428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 3528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhufrom webkitpy.common.system import logutils 366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfrom webkitpy.common.system import executive 3728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 3828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 3928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu_log = logutils.get_logger(__file__) 4028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 4128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# 426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner# FIXME: This is used to record if we've already hit the filesystem to look 4328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# for a default configuration. We cache this to speed up the unit tests, 446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner# but this can be reset with clear_cached_configuration(). This should be 456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner# replaced with us consistently using MockConfigs() for tests that don't 466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner# hit the filesystem at all and provide a reliable value. 4728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu# 486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner_have_determined_configuration = False 496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner_configuration = "Release" 5028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 5128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 5228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhudef clear_cached_configuration(): 536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner global _have_determined_configuration, _configuration 546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner _have_determined_configuration = False 556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner _configuration = "Release" 5628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 5728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 5828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuclass Config(object): 5928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu _FLAGS_FROM_CONFIGURATIONS = { 6028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu "Debug": "--debug", 6128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu "Release": "--release", 6228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } 6328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner def __init__(self, executive, filesystem): 6528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._executive = executive 666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner self._filesystem = filesystem 6728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._webkit_base_dir = None 6828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._default_configuration = None 6928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._build_directories = {} 7028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 7128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def build_directory(self, configuration): 7228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu """Returns the path to the build directory for the configuration.""" 7328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if configuration: 7428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu flags = ["--configuration", 7528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._FLAGS_FROM_CONFIGURATIONS[configuration]] 7628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu else: 7728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu configuration = "" 7828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu flags = ["--top-level"] 7928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 8028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if not self._build_directories.get(configuration): 8128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu args = ["perl", self._script_path("webkit-build-directory")] + flags 8228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._build_directories[configuration] = ( 8328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._executive.run_command(args).rstrip()) 8428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 8528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return self._build_directories[configuration] 8628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 8728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def build_dumprendertree(self, configuration): 8828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu """Builds DRT in the given configuration. 8928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 9028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu Returns True if the build was successful and up-to-date.""" 9128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu flag = self._FLAGS_FROM_CONFIGURATIONS[configuration] 9228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu exit_code = self._executive.run_command([ 9328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._script_path("build-dumprendertree"), flag], 9428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return_exit_code=True) 9528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if exit_code != 0: 9628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu _log.error("Failed to build DumpRenderTree") 9728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return False 9828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return True 9928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 10028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def default_configuration(self): 10128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu """Returns the default configuration for the user. 10228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 10328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu Returns the value set by 'set-webkit-configuration', or "Release" 10428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if that has not been set. This mirrors the logic in webkitdirs.pm.""" 10528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if not self._default_configuration: 10628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._default_configuration = self._determine_configuration() 10728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if not self._default_configuration: 10828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._default_configuration = 'Release' 10928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if self._default_configuration not in self._FLAGS_FROM_CONFIGURATIONS: 11028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu _log.warn("Configuration \"%s\" is not a recognized value.\n" % 11128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu self._default_configuration) 11228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu _log.warn("Scripts may fail. " 11328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu "See 'set-webkit-configuration --help'.") 11428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return self._default_configuration 11528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 11628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def path_from_webkit_base(self, *comps): 1176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.join(self.webkit_base_dir(), *comps) 11828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 11928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def webkit_base_dir(self): 12028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu """Returns the absolute path to the top of the WebKit tree. 12128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 12228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu Raises an AssertionError if the top dir can't be determined.""" 1236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Note: this code somewhat duplicates the code in 1246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # scm.find_checkout_root(). However, that code only works if the top 1256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # of the SCM repository also matches the top of the WebKit tree. The 1266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Chromium ports, for example, only check out subdirectories like 127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Tools/Scripts, and so we still have to do additional work 1286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # to find the top of the tree. 1296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # 1306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # This code will also work if there is no SCM system at all. 13128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if not self._webkit_base_dir: 132ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch abspath = self._filesystem.abspath(__file__) 133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._webkit_base_dir = abspath[0:abspath.find('Tools') - 1] 13428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return self._webkit_base_dir 13528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 13628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def _script_path(self, script_name): 137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return self._filesystem.join(self.webkit_base_dir(), "Tools", 1386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner "Scripts", script_name) 13928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 14028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def _determine_configuration(self): 14128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu # This mirrors the logic in webkitdirs.pm:determineConfiguration(). 1426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # 1436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # FIXME: See the comment at the top of the file regarding unit tests 1446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # and our use of global mutable static variables. 1456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner global _have_determined_configuration, _configuration 1466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not _have_determined_configuration: 14728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu contents = self._read_configuration() 1486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not contents: 1496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner contents = "Release" 15028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if contents == "Deployment": 15128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu contents = "Release" 15228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if contents == "Development": 15328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu contents = "Debug" 1546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner _configuration = contents 1556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner _have_determined_configuration = True 1566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return _configuration 15728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 15828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu def _read_configuration(self): 1596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner try: 1606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner configuration_path = self._filesystem.join(self.build_directory(None), 1616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner "Configuration") 1626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not self._filesystem.exists(configuration_path): 1636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return None 1646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner except (OSError, executive.ScriptError): 16528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu return None 16628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 1676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return self._filesystem.read_text_file(configuration_path).rstrip() 168