Home | History | Annotate | Download | only in port
      1 #!/usr/bin/env python
      2 # Copyright (C) 2010 Google Inc. All rights reserved.
      3 #
      4 # Redistribution and use in source and binary forms, with or without
      5 # modification, are permitted provided that the following conditions are
      6 # met:
      7 #
      8 #     * Redistributions of source code must retain the above copyright
      9 # notice, this list of conditions and the following disclaimer.
     10 #     * Redistributions in binary form must reproduce the above
     11 # copyright notice, this list of conditions and the following disclaimer
     12 # in the documentation and/or other materials provided with the
     13 # distribution.
     14 #     * Neither the name of Google Inc. nor the names of its
     15 # contributors may be used to endorse or promote products derived from
     16 # this software without specific prior written permission.
     17 #
     18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 """Wrapper objects for WebKit-specific utility routines."""
     31 
     32 # FIXME: This file needs to be unified with common/checkout/scm.py and
     33 # common/config/ports.py .
     34 
     35 from webkitpy.common.system import logutils
     36 from webkitpy.common.system import executive
     37 
     38 
     39 _log = logutils.get_logger(__file__)
     40 
     41 #
     42 # FIXME: This is used to record if we've already hit the filesystem to look
     43 # for a default configuration. We cache this to speed up the unit tests,
     44 # but this can be reset with clear_cached_configuration(). This should be
     45 # replaced with us consistently using MockConfigs() for tests that don't
     46 # hit the filesystem at all and provide a reliable value.
     47 #
     48 _have_determined_configuration = False
     49 _configuration = "Release"
     50 
     51 
     52 def clear_cached_configuration():
     53     global _have_determined_configuration, _configuration
     54     _have_determined_configuration = False
     55     _configuration = "Release"
     56 
     57 
     58 class Config(object):
     59     _FLAGS_FROM_CONFIGURATIONS = {
     60         "Debug": "--debug",
     61         "Release": "--release",
     62     }
     63 
     64     def __init__(self, executive, filesystem):
     65         self._executive = executive
     66         self._filesystem = filesystem
     67         self._webkit_base_dir = None
     68         self._default_configuration = None
     69         self._build_directories = {}
     70 
     71     def build_directory(self, configuration):
     72         """Returns the path to the build directory for the configuration."""
     73         if configuration:
     74             flags = ["--configuration",
     75                      self._FLAGS_FROM_CONFIGURATIONS[configuration]]
     76         else:
     77             configuration = ""
     78             flags = ["--top-level"]
     79 
     80         if not self._build_directories.get(configuration):
     81             args = ["perl", self._script_path("webkit-build-directory")] + flags
     82             self._build_directories[configuration] = (
     83                 self._executive.run_command(args).rstrip())
     84 
     85         return self._build_directories[configuration]
     86 
     87     def build_dumprendertree(self, configuration):
     88         """Builds DRT in the given configuration.
     89 
     90         Returns True if the  build was successful and up-to-date."""
     91         flag = self._FLAGS_FROM_CONFIGURATIONS[configuration]
     92         exit_code = self._executive.run_command([
     93             self._script_path("build-dumprendertree"), flag],
     94             return_exit_code=True)
     95         if exit_code != 0:
     96             _log.error("Failed to build DumpRenderTree")
     97             return False
     98         return True
     99 
    100     def default_configuration(self):
    101         """Returns the default configuration for the user.
    102 
    103         Returns the value set by 'set-webkit-configuration', or "Release"
    104         if that has not been set. This mirrors the logic in webkitdirs.pm."""
    105         if not self._default_configuration:
    106             self._default_configuration = self._determine_configuration()
    107         if not self._default_configuration:
    108             self._default_configuration = 'Release'
    109         if self._default_configuration not in self._FLAGS_FROM_CONFIGURATIONS:
    110             _log.warn("Configuration \"%s\" is not a recognized value.\n" %
    111                       self._default_configuration)
    112             _log.warn("Scripts may fail.  "
    113                       "See 'set-webkit-configuration --help'.")
    114         return self._default_configuration
    115 
    116     def path_from_webkit_base(self, *comps):
    117         return self._filesystem.join(self.webkit_base_dir(), *comps)
    118 
    119     def webkit_base_dir(self):
    120         """Returns the absolute path to the top of the WebKit tree.
    121 
    122         Raises an AssertionError if the top dir can't be determined."""
    123         # Note: this code somewhat duplicates the code in
    124         # scm.find_checkout_root(). However, that code only works if the top
    125         # of the SCM repository also matches the top of the WebKit tree. The
    126         # Chromium ports, for example, only check out subdirectories like
    127         # Tools/Scripts, and so we still have to do additional work
    128         # to find the top of the tree.
    129         #
    130         # This code will also work if there is no SCM system at all.
    131         if not self._webkit_base_dir:
    132             abspath = self._filesystem.abspath(__file__)
    133             self._webkit_base_dir = abspath[0:abspath.find('Tools') - 1]
    134         return self._webkit_base_dir
    135 
    136     def _script_path(self, script_name):
    137         return self._filesystem.join(self.webkit_base_dir(), "Tools",
    138                                      "Scripts", script_name)
    139 
    140     def _determine_configuration(self):
    141         # This mirrors the logic in webkitdirs.pm:determineConfiguration().
    142         #
    143         # FIXME: See the comment at the top of the file regarding unit tests
    144         # and our use of global mutable static variables.
    145         global _have_determined_configuration, _configuration
    146         if not _have_determined_configuration:
    147             contents = self._read_configuration()
    148             if not contents:
    149                 contents = "Release"
    150             if contents == "Deployment":
    151                 contents = "Release"
    152             if contents == "Development":
    153                 contents = "Debug"
    154             _configuration = contents
    155             _have_determined_configuration = True
    156         return _configuration
    157 
    158     def _read_configuration(self):
    159         try:
    160             configuration_path = self._filesystem.join(self.build_directory(None),
    161                                                        "Configuration")
    162             if not self._filesystem.exists(configuration_path):
    163                 return None
    164         except (OSError, executive.ScriptError):
    165             return None
    166 
    167         return self._filesystem.read_text_file(configuration_path).rstrip()
    168