2009-08-02 Kevin Ollivier <kevino@theolliviers.com>
[WebKit.git] / WebKitTools / wx / 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 glob
27 import os
28 import sys
29 import urllib
30 import urlparse
31
32 import Logs
33
34 def get_output(command):
35     """
36     Windows-compatible function for getting output from a command.
37     """
38     f = os.popen(command)
39     return f.read().strip()
40     
41 def get_excludes(root, patterns):
42     """
43     Get a list of exclude patterns going down several dirs. 
44     TODO: Make this fully recursive.
45     """
46     excludes = []
47     
48     for pattern in patterns:
49         subdir_pattern = os.sep + '*'
50         for subdir in [subdir_pattern, subdir_pattern*2, subdir_pattern*3]:
51             adir = root + subdir + os.sep + pattern
52             files = glob.glob(adir)
53             for afile in files:
54                 excludes.append(os.path.basename(afile))
55
56     return excludes
57     
58 def get_dirs_for_features(root, features, dirs):
59     """
60     Find which directories to include in the list of build dirs based upon the 
61     enabled port(s) and features.
62     """
63     outdirs = dirs
64     for adir in dirs:
65         for feature in features:
66             relpath = os.path.join(adir, feature)
67             featuredir = os.path.join(root, relpath)
68             if os.path.exists(featuredir) and not relpath in outdirs:
69                 outdirs.append(relpath)
70             
71     return outdirs
72
73 def download_if_newer(url, destdir):
74     """
75     Checks if the file on the server is newer than the one in the user's tree,
76     and if so, downloads it. 
77     
78     Returns the filename of the downloaded file if downloaded, or None if 
79     the existing file matches the one on the server.
80     """
81     obj = urlparse.urlparse(url)
82     filename = os.path.basename(obj.path)
83     destfile = os.path.join(destdir, filename)
84     
85     urlobj = urllib.urlopen(url)
86     size = long(urlobj.info().getheader('Content-Length'))
87
88     def download_callback(downloaded, block_size, total_size): 
89         downloaded = block_size * downloaded
90         if downloaded > total_size:
91             downloaded = total_size
92         sys.stdout.write('%s %d of %d bytes downloaded\r' % (filename, downloaded, total_size))
93     
94     # NB: We don't check modified time as Python doesn't yet handle timezone conversion
95     # properly when converting strings to time objects.
96     if not os.path.exists(destfile) or os.path.getsize(destfile) != size:
97         urllib.urlretrieve(url, destfile, download_callback)
98         print ''
99         return destfile
100     
101     return None
102     
103 def update_wx_deps(wk_root, msvc_version='msvc2008'):
104     """
105     Download and update tools needed to build the wx port.
106     """
107     Logs.info('Ensuring wxWebKit dependencies are up-to-date.')
108     
109     wklibs_dir = os.path.join(wk_root, 'WebKitLibraries')
110     waf = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/waf', os.path.join(wk_root, 'WebKitTools', 'wx'))
111     if waf:
112         # TODO: Make the build restart itself after an update.
113         Logs.warn('Build system updated, please restart build.')
114         sys.exit(1)
115
116     # since this module is still experimental
117     #swig_module = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/swig.py', os.path.join(wk_root, 'WebKit', 'wx', 'bindings', 'python'))
118
119     if sys.platform.startswith('win'):
120         Logs.info('downloading deps package')
121         archive = download_if_newer('http://wxwebkit.wxcommunity.com/downloads/deps/wxWebKitDeps-%s.zip' % msvc_version, wklibs_dir)
122         if archive and os.path.exists(archive):
123             os.system('unzip -o %s -d %s' % (archive, os.path.join(wklibs_dir, msvc_version)))
124     
125     elif sys.platform.startswith('darwin'):
126         os.system('%s/WebKitTools/wx/install-unix-extras' % wk_root)
127         
128 def includeDirsForSources(sources):
129     include_dirs = []
130     for group in sources:
131         for source in group:
132             dirname = os.path.dirname(source)
133             if not dirname in include_dirs:
134                 include_dirs.append(dirname)
135             
136     return include_dirs
137
138 def flattenSources(sources):
139     flat_sources = []
140     for group in sources:
141         flat_sources.extend(group)
142         
143     return flat_sources