webkitpy: clean up options for specifying multiple platforms at once
[WebKit-https.git] / Tools / Scripts / webkitpy / layout_tests / port / factory.py
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 """Factory method to retrieve the appropriate port implementation."""
31
32 import fnmatch
33 import optparse
34 import re
35
36 from webkitpy.layout_tests.port import builders
37
38
39 def platform_options(use_globs=False):
40     return [
41         optparse.make_option('--platform', action='store',
42             help=('Glob-style list of platform/ports to use (e.g., "mac*")' if use_globs else 'Platform to use (e.g., "mac-lion")')),
43         optparse.make_option('--chromium', action='store_const', dest='platform',
44             const=('chromium*' if use_globs else 'chromium'),
45             help=('Alias for --platform=chromium*' if use_globs else 'Alias for --platform=chromium')),
46         optparse.make_option('--chromium-android', action='store_const', dest='platform',
47             const=('chromium-android*' if use_globs else 'chromium-android'),
48             help=('Alias for --platform=chromium-android*' if use_globs else 'Alias for --platform=chromium')),
49         optparse.make_option('--efl', action='store_const', dest='platform',
50             const=('efl*' if use_globs else 'efl'),
51             help=('Alias for --platform=efl*' if use_globs else 'Alias for --platform=efl')),
52         optparse.make_option('--gtk', action='store_const', dest='platform',
53             const=('gtk*' if use_globs else 'gtk'),
54             help=('Alias for --platform=gtk*' if use_globs else 'Alias for --platform=gtk')),
55         optparse.make_option('--qt', action='store_const', dest="platform",
56             const=('qt*' if use_globs else 'qt'),
57             help=('Alias for --platform=qt' if use_globs else 'Alias for --platform=qt')),
58         ]
59
60
61 def configuration_options():
62     return [
63         optparse.make_option("-t", "--target", dest="configuration", help="(DEPRECATED)"),
64         # FIXME: --help should display which configuration is default.
65         optparse.make_option('--debug', action='store_const', const='Debug', dest="configuration",
66             help='Set the configuration to Debug'),
67         optparse.make_option('--release', action='store_const', const='Release', dest="configuration",
68             help='Set the configuration to Release'),
69         optparse.make_option('--32-bit', action='store_const', const='x86', default=None, dest="architecture",
70             help='use 32-bit binaries by default (x86 instead of x86_64)'),
71         ]
72
73
74
75 def _builder_options(builder_name):
76     configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release"
77     is_webkit2 = builder_name.find("WK2") != -1
78     builder_name = builder_name
79     return optparse.Values({'builder_name': builder_name, 'configuration': configuration, 'webkit_test_runner': is_webkit2})
80
81
82 class PortFactory(object):
83     PORT_CLASSES = (
84         'chromium_android.ChromiumAndroidPort',
85         'chromium_linux.ChromiumLinuxPort',
86         'chromium_mac.ChromiumMacPort',
87         'chromium_win.ChromiumWinPort',
88         'efl.EflPort',
89         'gtk.GtkPort',
90         'mac.MacPort',
91         'mock_drt.MockDRTPort',
92         'qt.QtPort',
93         'test.TestPort',
94         'win.WinPort',
95     )
96
97     def __init__(self, host):
98         self._host = host
99
100     def _default_port(self, options):
101         platform = self._host.platform
102         if platform.is_linux() or platform.is_freebsd():
103             return 'chromium-linux'
104         elif platform.is_mac():
105             return 'mac'
106         elif platform.is_win():
107             return 'win'
108         raise NotImplementedError('unknown platform: %s' % platform)
109
110     def get(self, port_name=None, options=None, **kwargs):
111         """Returns an object implementing the Port interface. If
112         port_name is None, this routine attempts to guess at the most
113         appropriate port on this platform."""
114         port_name = port_name or self._default_port(options)
115
116         # FIXME(dpranke): We special-case '--platform chromium' so that it can co-exist
117         # with '--platform chromium-mac' and '--platform chromium-linux' properly (we
118         # can't look at the port_name prefix in this case).
119         if port_name == 'chromium':
120             port_name = 'chromium-' + self._host.platform.os_name
121
122         for port_class in self.PORT_CLASSES:
123             module_name, class_name = port_class.rsplit('.', 1)
124             module = __import__(module_name, globals(), locals(), [], -1)
125             cls = module.__dict__[class_name]
126             if port_name.startswith(cls.port_name):
127                 port_name = cls.determine_full_port_name(self._host, options, port_name)
128                 return cls(self._host, port_name, options=options, **kwargs)
129         raise NotImplementedError('unsupported platform: "%s"' % port_name)
130
131     def all_port_names(self, platform=None):
132         """Return a list of all valid, fully-specified, "real" port names.
133
134         This is the list of directories that are used as actual baseline_paths()
135         by real ports. This does not include any "fake" names like "test"
136         or "mock-mac", and it does not include any directories that are not.
137
138         If platform is not specified, we will glob-match all ports"""
139         platform = platform or '*'
140         return fnmatch.filter(builders.all_port_names(), platform)
141
142     def get_from_builder_name(self, builder_name):
143         port_name = builders.port_name_for_builder_name(builder_name)
144         assert port_name, "unrecognized builder name '%s'" % builder_name
145         return self.get(port_name, _builder_options(builder_name))