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 26import commands 27import glob 28import os 29import platform 30import re 31import shutil 32import sys 33import urllib 34import urlparse 35 36def get_output(command): 37 """ 38 Windows-compatible function for getting output from a command. 39 """ 40 if sys.platform.startswith('win'): 41 f = os.popen(command) 42 return f.read().strip() 43 else: 44 return commands.getoutput(command) 45 46def get_excludes(root, patterns): 47 """ 48 Get a list of exclude patterns going down several dirs. 49 TODO: Make this fully recursive. 50 """ 51 excludes = [] 52 53 for pattern in patterns: 54 subdir_pattern = os.sep + '*' 55 for subdir in [subdir_pattern, subdir_pattern*2, subdir_pattern*3]: 56 adir = root + subdir + os.sep + pattern 57 files = glob.glob(adir) 58 for afile in files: 59 excludes.append(os.path.basename(afile)) 60 61 return excludes 62 63def get_dirs_for_features(root, features, dirs): 64 """ 65 Find which directories to include in the list of build dirs based upon the 66 enabled port(s) and features. 67 """ 68 outdirs = dirs 69 for adir in dirs: 70 for feature in features: 71 relpath = os.path.join(adir, feature) 72 featuredir = os.path.join(root, relpath) 73 if os.path.exists(featuredir) and not relpath in outdirs: 74 outdirs.append(relpath) 75 76 return outdirs 77 78def download_if_newer(url, destdir): 79 """ 80 Checks if the file on the server is newer than the one in the user's tree, 81 and if so, downloads it. 82 83 Returns the filename of the downloaded file if downloaded, or None if 84 the existing file matches the one on the server. 85 """ 86 obj = urlparse.urlparse(url) 87 filename = os.path.basename(obj.path) 88 destfile = os.path.join(destdir, filename) 89 90 urlobj = urllib.urlopen(url) 91 size = long(urlobj.info().getheader('Content-Length')) 92 93 def download_callback(downloaded, block_size, total_size): 94 downloaded = block_size * downloaded 95 if downloaded > total_size: 96 downloaded = total_size 97 sys.stdout.write('%s %d of %d bytes downloaded\r' % (filename, downloaded, total_size)) 98 99 # NB: We don't check modified time as Python doesn't yet handle timezone conversion 100 # properly when converting strings to time objects. 101 if not os.path.exists(destfile) or os.path.getsize(destfile) != size: 102 urllib.urlretrieve(url, destfile, download_callback) 103 print '' 104 return destfile 105 106 return None 107 108def update_wx_deps(conf, wk_root, msvc_version='msvc2008'): 109 """ 110 Download and update tools needed to build the wx port. 111 """ 112 import Logs 113 Logs.info('Ensuring wxWebKit dependencies are up-to-date.') 114 115 wklibs_dir = os.path.join(wk_root, 'WebKitLibraries') 116 waf = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/waf', os.path.join(wk_root, 'Tools', 'wx')) 117 if waf: 118 # TODO: Make the build restart itself after an update. 119 Logs.warn('Build system updated, please restart build.') 120 sys.exit(1) 121 122 # since this module is still experimental 123 wxpy_dir = os.path.join(wk_root, 'Source', 'WebKit', 'wx', 'bindings', 'python') 124 swig_module = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/swig.py.txt', wxpy_dir) 125 if swig_module: 126 shutil.copy(os.path.join(wxpy_dir, 'swig.py.txt'), os.path.join(wxpy_dir, 'swig.py')) 127 128 if sys.platform.startswith('win'): 129 Logs.info('downloading deps package') 130 archive = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/wxWebKitDeps-%s.zip' % msvc_version, wklibs_dir) 131 if archive and os.path.exists(archive): 132 os.system('unzip -o %s -d %s' % (archive, os.path.join(wklibs_dir, msvc_version))) 133 134 elif sys.platform.startswith('darwin'): 135 # export the right compiler for building the dependencies 136 if platform.release().startswith('10'): # Snow Leopard 137 os.environ['CC'] = conf.env['CC'][0] 138 os.environ['CXX'] = conf.env['CXX'][0] 139 os.system('%s/Tools/wx/install-unix-extras' % wk_root) 140 141def includeDirsForSources(sources): 142 include_dirs = [] 143 for group in sources: 144 for source in group: 145 dirname = os.path.dirname(source) 146 if not dirname in include_dirs: 147 include_dirs.append(dirname) 148 149 return include_dirs 150 151def flattenSources(sources): 152 flat_sources = [] 153 for group in sources: 154 flat_sources.extend(group) 155 156 return flat_sources 157 158def git_branch_name(): 159 try: 160 branches = commands.getoutput("git branch --no-color") 161 match = re.search('^\* (.*)', branches, re.MULTILINE) 162 if match: 163 return ".%s" % match.group(1) 164 except: 165 pass 166 167 return "" 168 169def get_config(wk_root): 170 config_file = os.path.join(wk_root, 'WebKitBuild', 'Configuration') 171 config = 'Debug' 172 173 if os.path.exists(config_file): 174 config = open(config_file).read() 175 176 return config 177 178def svn_revision(): 179 if os.system("git-svn info") == 0: 180 info = commands.getoutput("git-svn info ../..") 181 else: 182 info = commands.getoutput("svn info") 183 184 for line in info.split("\n"): 185 if line.startswith("Revision: "): 186 return line.replace("Revision: ", "").strip() 187 188 return "" 189