Unreviewed, rolling out r163530.
[WebKit-https.git] / Tools / gtk / common.py
1 #!/usr/bin/env python
2 # Copyright (C) 2011 Igalia S.L.
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17
18 import errno
19 import os
20 import select
21 import subprocess
22 import sys
23
24 script_dir = None
25 build_dir = None
26 library_build_dir = None
27 tests_library_build_dir = None
28 is_cmake = None
29 build_types = ('Release', 'Debug')
30
31
32 def set_build_types(new_build_types):
33     global build_types
34     build_types = new_build_types
35
36
37 def is_cmake_build():
38     global is_cmake
39     if is_cmake is None:
40         is_cmake = os.path.exists(build_path('CMakeCache.txt'))
41     return is_cmake
42
43
44 def library_build_path(*args):
45     global library_build_dir
46     if not library_build_dir:
47         if is_cmake_build():
48             library_build_dir = build_path('lib', *args)
49         else:
50             library_build_dir = build_path('.libs', *args)
51     return library_build_dir
52
53
54 def tests_library_build_path(*args):
55     if is_cmake_build():
56         return library_build_path(*args)
57
58     global tests_library_build_dir
59     if not tests_library_build_dir:
60         tests_library_build_dir = build_path('Libraries', *args)
61     return tests_library_build_dir
62
63
64 def binary_build_path(*args):
65     global library_build_dir
66     if not library_build_dir:
67         if is_cmake_build():
68             library_build_dir = build_path('bin', *args)
69         else:
70             library_build_dir = build_path('Programs', *args)
71     return library_build_dir
72
73
74 def script_path(*args):
75     global script_dir
76     if not script_dir:
77         script_dir = os.path.join(os.path.dirname(__file__), '..', 'Scripts')
78     return os.path.join(*(script_dir,) + args)
79
80
81 def top_level_path(*args):
82     return os.path.join(*((os.path.join(os.path.dirname(__file__), '..', '..'),) + args))
83
84
85 def get_build_path(fatal=True):
86     global build_dir
87     if build_dir:
88         return build_dir
89
90     def is_valid_build_directory(path):
91         return os.path.exists(os.path.join(path, 'GNUmakefile')) or \
92             os.path.exists(os.path.join(path, 'Programs', 'GtkLauncher')) or \
93             os.path.exists(os.path.join(path, 'Programs', 'MiniBrowser')) or \
94             os.path.exists(os.path.join(path, 'CMakeCache.txt')) or \
95             os.path.exists(os.path.join(path, 'bin/GtkLauncher')) or \
96             os.path.exists(os.path.join(path, 'bin/MiniBrowser'))
97
98     if len(sys.argv[1:]) > 1 and os.path.exists(sys.argv[-1]) and is_valid_build_directory(sys.argv[-1]):
99         return sys.argv[-1]
100
101     # Debian and Ubuntu build both flavours of the library (with gtk2
102     # and with gtk3); they use directories build-2.0 and build-3.0 for
103     # that, which is not handled by the above cases; we check that the
104     # directory where we are called from is a valid build directory,
105     # which should handle pretty much all other non-standard cases.
106     build_dir = os.getcwd()
107     if is_valid_build_directory(build_dir):
108         return build_dir
109
110     global build_types
111     for build_type in build_types:
112         build_dir = top_level_path('WebKitBuild', build_type)
113         if is_valid_build_directory(build_dir):
114             return build_dir
115
116     # distcheck builds in a directory named _build in the top-level path.
117     build_dir = top_level_path("_build")
118     if is_valid_build_directory(build_dir):
119         return build_dir
120
121     build_dir = top_level_path()
122     if is_valid_build_directory(build_dir):
123         return build_dir
124
125     build_dir = top_level_path("WebKitBuild")
126     if is_valid_build_directory(build_dir):
127         return build_dir
128
129     print('Could not determine build directory.')
130     if fatal:
131         sys.exit(1)
132
133
134 def build_path(*args):
135     return os.path.join(*(get_build_path(),) + args)
136
137
138 def pkg_config_file_variable(package, variable):
139     process = subprocess.Popen(['pkg-config', '--variable=%s' % variable, package],
140                                stdout=subprocess.PIPE)
141     stdout = process.communicate()[0].decode("utf-8")
142     if process.returncode:
143         return None
144     return stdout.strip()
145
146
147 def prefix_of_pkg_config_file(package):
148     return pkg_config_file_variable(package, 'prefix')
149
150
151 def gtk_version_of_pkg_config_file(pkg_config_path):
152     process = subprocess.Popen(['pkg-config', pkg_config_path, '--print-requires'],
153                                stdout=subprocess.PIPE)
154     stdout = process.communicate()[0].decode("utf-8")
155
156     if 'gtk+-3.0' in stdout:
157         return 3
158     return 2
159
160
161 def parse_output_lines(fd, parse_line_callback):
162     output = ''
163     read_set = [fd]
164     while read_set:
165         try:
166             rlist, wlist, xlist = select.select(read_set, [], [])
167         except select.error as e:
168             parse_line_callback("WARNING: error while waiting for fd %d to become readable\n" % fd)
169             parse_line_callback("    error code: %d, error message: %s\n" % (e[0], e[1]))
170             continue
171
172         if fd in rlist:
173             try:
174                 chunk = os.read(fd, 1024)
175             except OSError as e:
176                 if e.errno == errno.EIO:
177                     # Child process finished.
178                     chunk = ''
179                 else:
180                     raise e
181             if not chunk:
182                 read_set.remove(fd)
183
184             output += chunk
185             while '\n' in output:
186                 pos = output.find('\n')
187                 parse_line_callback(output[:pos + 1])
188                 output = output[pos + 1:]
189
190             if not chunk and output:
191                 parse_line_callback(output)
192                 output = ''