WebAssembly: Make our calls out to JS PIC friendly
[WebKit-https.git] / Tools / BuildSlaveSupport / built-product-archive
1 #!/usr/bin/python
2
3 # Copyright (C) 2009, 2015 Apple Inc.  All rights reserved.
4 # Copyright (C) 2012 Google Inc. All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # 1.  Redistributions of source code must retain the above copyright
11 #     notice, this list of conditions and the following disclaimer. 
12 # 2.  Redistributions in binary form must reproduce the above copyright
13 #     notice, this list of conditions and the following disclaimer in the
14 #     documentation and/or other materials provided with the distribution. 
15 #
16 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
17 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
20 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 import errno
28 import optparse
29 import os
30 import shutil
31 import subprocess
32 import sys
33 import zipfile
34
35 _configurationBuildDirectory = None
36 _topLevelBuildDirectory = None
37
38
39 def main():
40     parser = optparse.OptionParser("usage: %prog [options] [action]")
41     parser.add_option("--platform", dest="platform")
42     parser.add_option("--debug", action="store_const", const="debug", dest="configuration")
43     parser.add_option("--release", action="store_const", const="release", dest="configuration")
44
45     options, (action, ) = parser.parse_args()
46     if not options.platform:
47         parser.error("Platform is required")
48         return 1
49     if not options.configuration:
50         parser.error("Configuration is required")
51         return 1
52     if action not in ('archive', 'extract'):
53         parser.error("Action is required")
54         return 1
55
56     genericPlatform = options.platform.split('-', 1)[0]
57     determineWebKitBuildDirectories(genericPlatform, options.platform, options.configuration)
58     if not _topLevelBuildDirectory:
59         print >> sys.stderr, 'Could not determine top-level build directory'
60         return 1
61     if not _configurationBuildDirectory:
62         print >> sys.stderr, 'Could not determine configuration-specific build directory'
63         return 1
64
65     if action == 'archive':
66         return archiveBuiltProduct(options.configuration, genericPlatform, options.platform)
67     else:
68         return extractBuiltProduct(options.configuration, genericPlatform)
69
70
71 def webkitBuildDirectoryForConfigurationAndPlatform(configuration, platform, fullPlatform='', returnTopLevelDirectory=False):
72     if fullPlatform.startswith('ios-simulator'):
73         platform = 'ios-simulator'
74     elif platform == 'ios':
75         platform = 'device'
76     command = ['perl', os.path.join(os.path.dirname(__file__), '..', 'Scripts', 'webkit-build-directory'), '--' + platform, '--' + configuration]
77     if returnTopLevelDirectory:
78         command += ['--top-level']
79     else:
80         command += ['--configuration']
81     return subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip()
82
83
84 def determineWebKitBuildDirectories(platform, fullPlatform, configuration):
85     global _configurationBuildDirectory
86     global _topLevelBuildDirectory
87     _configurationBuildDirectory = webkitBuildDirectoryForConfigurationAndPlatform(configuration, platform, fullPlatform)
88     _topLevelBuildDirectory = webkitBuildDirectoryForConfigurationAndPlatform(configuration, platform, fullPlatform, returnTopLevelDirectory=True)
89     return _topLevelBuildDirectory
90
91
92 def removeDirectoryIfExists(thinDirectory):
93     if os.path.isdir(thinDirectory):
94         shutil.rmtree(thinDirectory)
95
96
97 def copyBuildFiles(source, destination, patterns):
98     shutil.copytree(source, destination, ignore=shutil.ignore_patterns(*patterns))
99
100
101 def createZipFromList(listToZip, configuration, excludePattern=None):
102     archiveDir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'WebKitBuild'))
103     archiveFile = os.path.join(archiveDir, configuration + '.zip')
104
105     try:
106         os.unlink(archiveFile)
107     except OSError, e:
108         if e.errno != errno.ENOENT:
109             raise
110
111     if sys.platform.startswith('linux'):
112         zipCommand = ['zip', '-y', '-r', archiveFile] + listToZip
113         if excludePattern:
114             zipCommand += ['-x', excludePattern]
115         return subprocess.call(zipCommand, cwd=_configurationBuildDirectory)
116
117     raise NotImplementedError('Unsupported platform: {platform}'.format(platform=sys.platform))
118
119
120 def createZipManually(directoryToZip, archiveFile):
121     archiveZip = zipfile.ZipFile(archiveFile, "w")
122
123     for path, dirNames, fileNames in os.walk(directoryToZip):
124         relativePath = os.path.relpath(path, directoryToZip)
125         for fileName in fileNames:
126             archiveZip.write(os.path.join(path, fileName), os.path.join(relativePath, fileName))
127
128     archiveZip.close()
129
130
131 def createZip(directoryToZip, configuration, embedParentDirectoryNameOnDarwin=False):
132     archiveDir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "WebKitBuild"))
133     archiveFile = os.path.join(archiveDir, configuration + ".zip")
134
135     try:
136         os.unlink(archiveFile)
137     except OSError, e:
138         if e.errno != errno.ENOENT:
139             raise
140
141     if sys.platform == 'darwin':
142         command = ['ditto', '-c', '-k', '--sequesterRsrc']
143         if embedParentDirectoryNameOnDarwin:
144             command += ['--keepParent']
145         command += [directoryToZip, archiveFile]
146         return subprocess.call(command)
147     elif sys.platform == 'cygwin':
148         return subprocess.call(["zip", "-r", archiveFile, "bin32"], cwd=directoryToZip)
149     elif sys.platform == 'win32':
150         createZipManually(directoryToZip, archiveFile)
151         return 0
152     elif sys.platform.startswith('linux'):
153         return subprocess.call(["zip", "-y", "-r", archiveFile, "."], cwd=directoryToZip)
154
155
156 def dirContainsdwo(directory):
157     sourcedir = os.path.join(_configurationBuildDirectory, directory)
158     for root, dirs, files in os.walk(sourcedir, topdown=False):
159         for name in files:
160             if name.endswith(".dwo"):
161                 return True
162     return False
163
164
165 def archiveBuiltProduct(configuration, platform, fullPlatform):
166     assert platform in ('mac', 'win', 'gtk', 'efl', 'ios')
167
168     # FIXME: ImageDiff should be built with the host SDK, <rdar://problem/30266038>.
169     # An approach similar to the one used for LayoutTestRelay in r190515 should be imlemented.
170     if platform in ('mac', 'ios'):
171         return createZip(_configurationBuildDirectory, configuration, embedParentDirectoryNameOnDarwin=True)
172     elif platform == 'win':
173         # FIXME: We shouldn't hardcode the assumption of a 32-bit build. See <https://bugs.webkit.org/show_bug.cgi?id=149715>.
174         binDirectory = os.path.join(_configurationBuildDirectory, 'bin32')
175         thinDirectory = os.path.join(_configurationBuildDirectory, 'thin')
176         thinBinDirectory = os.path.join(thinDirectory, "bin32")
177
178         removeDirectoryIfExists(thinDirectory)
179         copyBuildFiles(binDirectory, thinBinDirectory, ['*.ilk'])
180         if createZip(thinDirectory, configuration):
181             return 1
182
183         shutil.rmtree(thinDirectory)
184
185     elif platform == 'gtk' or platform == 'efl':
186         # On GTK+/EFL we don't need the intermediate step of creating a thinDirectory
187         # to be compressed in a ZIP file, because we can create the ZIP directly.
188         # This is faster and requires less disk resources.
189         neededDirectories = ['bin', 'lib']
190         # When debug fission is enabled the directories below contain dwo files
191         # with the debug information needed to generate backtraces with GDB.
192         for objectDir in ['Tools', 'Source']:
193             if dirContainsdwo(objectDir):
194                 neededDirectories.append(objectDir)
195
196         if createZipFromList(neededDirectories, configuration, excludePattern='*.o'):
197             return 1
198
199 def unzipArchive(directoryToExtractTo, configuration):
200     archiveDir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "WebKitBuild"))
201     assert os.path.isdir(archiveDir)
202     archiveFile = os.path.join(archiveDir, configuration + ".zip")
203
204     if sys.platform == 'darwin':
205         if subprocess.call(["ditto", "-x", "-k", archiveFile, directoryToExtractTo]):
206             return 1
207     elif sys.platform == 'cygwin' or sys.platform.startswith('linux'):
208         if subprocess.call(["unzip", "-o", archiveFile], cwd=directoryToExtractTo):
209             return 1
210     elif sys.platform == 'win32':
211         archive = zipfile.ZipFile(archiveFile, "r")
212         archive.extractall(directoryToExtractTo)
213         archive.close()
214
215     os.unlink(archiveFile)
216
217
218 def extractBuiltProduct(configuration, platform):
219     assert platform in ('mac', 'win', 'gtk', 'efl', 'ios')
220
221     archiveFile = os.path.join(_topLevelBuildDirectory, configuration + '.zip')
222
223     removeDirectoryIfExists(_configurationBuildDirectory)
224     os.makedirs(_configurationBuildDirectory)
225
226     if platform in ('mac', 'ios'):
227         return unzipArchive(_topLevelBuildDirectory, configuration)
228     elif platform == 'win' or platform == 'gtk' or platform == 'efl':
229         print 'Extracting', _configurationBuildDirectory
230         return unzipArchive(_configurationBuildDirectory, configuration)
231
232
233 if __name__ == '__main__':
234     sys.exit(main())