[wx] Unreviewed build fix, make sure the waf build checks the webKitBranchBuild
[WebKit-https.git] / Tools / waf / build / build_utils.py
1 # Copyright (C) 2009 Kevin Ollivier  All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
16 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 #
24 # Helper functions for the WebKit build.
25
26 import commands
27 import glob
28 import os
29 import platform
30 import re
31 import shutil
32 import sys
33 import urllib
34 import urlparse
35
36
37 def get_output(command):
38     """
39     Windows-compatible function for getting output from a command.
40     """
41     if sys.platform.startswith('win'):
42         f = os.popen(command)
43         return f.read().strip()
44     else:
45         return commands.getoutput(command)
46
47
48 def get_excludes(root, patterns):
49     """
50     Get a list of exclude patterns going down several dirs.
51     TODO: Make this fully recursive.
52     """
53     excludes = []
54
55     for pattern in patterns:
56         subdir_pattern = os.sep + '*'
57         for subdir in [subdir_pattern, subdir_pattern * 2, subdir_pattern * 3]:
58             adir = root + subdir + os.sep + pattern
59             files = glob.glob(adir)
60             for afile in files:
61                 excludes.append(os.path.basename(afile))
62
63     return excludes
64
65
66 def get_dirs_for_features(root, features, dirs):
67     """
68     Find which directories to include in the list of build dirs based upon the
69     enabled port(s) and features.
70     """
71     outdirs = dirs
72     for adir in dirs:
73         for feature in features:
74             relpath = os.path.join(adir, feature)
75             featuredir = os.path.join(root, relpath)
76             if os.path.exists(featuredir) and not relpath in outdirs:
77                 outdirs.append(relpath)
78
79     return outdirs
80
81
82 def download_if_newer(url, destdir):
83     """
84     Checks if the file on the server is newer than the one in the user's tree,
85     and if so, downloads it.
86
87     Returns the filename of the downloaded file if downloaded, or None if
88     the existing file matches the one on the server.
89     """
90     obj = urlparse.urlparse(url)
91     filename = os.path.basename(obj.path)
92     destfile = os.path.join(destdir, filename)
93
94     urlobj = urllib.urlopen(url)
95     size = long(urlobj.info().getheader('Content-Length'))
96
97     def download_callback(downloaded, block_size, total_size):
98         downloaded = block_size * downloaded
99         if downloaded > total_size:
100             downloaded = total_size
101         sys.stdout.write('%s %d of %d bytes downloaded\r' % (filename, downloaded, total_size))
102
103     # NB: We don't check modified time as Python doesn't yet handle timezone conversion
104     # properly when converting strings to time objects.
105     if not os.path.exists(destfile) or os.path.getsize(destfile) != size:
106         urllib.urlretrieve(url, destfile, download_callback)
107         print ''
108         return destfile
109
110     return None
111
112
113 def update_wx_deps(conf, wk_root, msvc_version='msvc2008'):
114     """
115     Download and update tools needed to build the wx port.
116     """
117     import Logs
118     Logs.info('Ensuring wxWebKit dependencies are up-to-date.')
119
120     wklibs_dir = os.path.join(wk_root, 'WebKitLibraries')
121     waf = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/waf', os.path.join(wk_root, 'Tools', 'wx'))
122     if waf:
123         # TODO: Make the build restart itself after an update.
124         Logs.warn('Build system updated, please restart build.')
125         sys.exit(1)
126
127     # since this module is still experimental
128     wxpy_dir = os.path.join(wk_root, 'Source', 'WebKit', 'wx', 'bindings', 'python')
129     swig_module = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/swig.py.txt', wxpy_dir)
130     if swig_module:
131         shutil.copy(os.path.join(wxpy_dir, 'swig.py.txt'), os.path.join(wxpy_dir, 'swig.py'))
132
133     if sys.platform.startswith('win'):
134         Logs.info('downloading deps package')
135         archive = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/wxWebKitDeps-%s.zip' % msvc_version, wklibs_dir)
136         if archive and os.path.exists(archive):
137             os.system('unzip -o %s -d %s' % (archive, os.path.join(wklibs_dir, msvc_version)))
138
139     elif sys.platform.startswith('darwin'):
140         # export the right compiler for building the dependencies
141         if platform.release().startswith('10'):  # Snow Leopard
142             os.environ['CC'] = conf.env['CC'][0]
143             os.environ['CXX'] = conf.env['CXX'][0]
144         os.system('%s/Tools/wx/install-unix-extras' % wk_root)
145
146
147 def includeDirsForSources(sources):
148     include_dirs = []
149     for group in sources:
150         for source in group:
151             dirname = os.path.dirname(source)
152             if not dirname in include_dirs:
153                 include_dirs.append(dirname)
154
155     return include_dirs
156
157
158 def flattenSources(sources):
159     flat_sources = []
160     for group in sources:
161         flat_sources.extend(group)
162
163     return flat_sources
164
165 def git_branch_name():
166     try:
167         branches = commands.getoutput("git branch --no-color")
168         match = re.search('^\* (.*)', branches, re.MULTILINE)
169         if match:
170             return "%s" % match.group(1)
171     except:
172         pass
173
174     return ""
175
176 def is_git_branch_build():
177     branch = git_branch_name()
178     is_branch_build = commands.getoutput("git config --bool branch.%s.webKitBranchBuild" % branch)
179     if is_branch_build == "true":
180         return True
181     elif is_branch_build == "false":
182         return False
183         
184     # not defined for this branch, use the default
185     is_branch_build = commands.getoutput("git config --bool core.webKitBranchBuild")
186     return is_branch_build == "true"
187
188 def get_base_product_dir(wk_root):
189     build_dir = os.path.join(wk_root, 'WebKitBuild')
190     git_branch = git_branch_name()
191     if git_branch != "" and is_git_branch_build():
192         build_dir = os.path.join(build_dir, git_branch)
193         
194     return build_dir
195
196 def get_config(wk_root):
197     config_file = os.path.join(get_base_product_dir(wk_root), 'Configuration')
198     config = 'Debug'
199
200     if os.path.exists(config_file):
201         config = open(config_file).read()
202
203     return config
204
205
206 def get_arch(wk_root):
207     arch_file = os.path.join(get_base_product_dir(wk_root), 'Architecture')
208     arch = 'x86_64'
209
210     if os.path.exists(arch_file):
211         arch = open(arch_file).read()
212
213     return arch
214
215
216 def svn_revision():
217     if os.system("git-svn info") == 0:
218         info = commands.getoutput("git-svn info ../..")
219     else:
220         info = commands.getoutput("svn info")
221
222     for line in info.split("\n"):
223         if line.startswith("Revision: "):
224             return line.replace("Revision: ", "").strip()
225
226     return ""