Rebaseline svg/custom/foreignObject-crash-on-hover.xml.
[chromium-blink-merge.git] / gears / SConscript.installers
blob4cefdb15074c55f9af4473152d3dd133826b71aa
1 # Copyright (c) 2008 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import fnmatch
6 import os
7 import re
8 import shutil
9 import subprocess
10 import utils
11 import SCons.Node
13 Import('env')
15 env = env.Clone()
17 if env['OS'] in ['win32', 'wince']:
18   env.Append(DATE = 'echo %DATE%.%TIME%')
19 else:
20   env.Append(DATE = 'date')
22 def GetInputs(var): return utils.GetInputs(var, env)
24 def Shell(cmd):
25   """Execute a shell command and return the output."""
26   cmd[0] = env.Entry(cmd[0]).abspath
27   cmd = env.subst(cmd)
28   return subprocess.Popen(
29       cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
31 if env['OS'] == 'win32':
32   def GGUIDGen(value):
33     """Generate a GGUID for the given value."""
34     return Shell(['$GGUIDGEN', '$NAMESPACE_GUID', value + '-$VERSION'])
35   env.Replace(
36       GGUIDGEN = '#/$OPEN_DIR/tools/gguidgen.exe',
37       NAMESPACE_GUID = '36F65206-5D4E-4752-9D52-27708E10DA79',
38 # MSI version numbers must have the form <major>.<minor>.<build>. To meet this,
39 # we combine our build and patch version numbers like so:
40 # MSI_VERSION = <major>.<minor>.<BUILD * 100 + PATCH>.
41 # Note: This assumes that the BUILD and PATCH variables adhere to the range
42 # requirements in version.mk. See comments in version.mk for more details.
43       MSI_BUILD = eval(env.subst('$BUILD * 100 + $PATCH')),
44       MSI_VERSION = '${MAJOR}.${MINOR}.${MSI_BUILD}',
45   )
47   # Building wxiobjs with candle
48   env.Replace(
49       CANDLEDEFPREFIX = '-d',
50       CANDLEDEFSUFFIX = '',
51       _CANDLEDEFFLAGS = ('${_defines(CANDLEDEFPREFIX, CANDLEDEFINES, '
52                          'CANDLEDEFSUFFIX, __env__)}'),
53       CANDLECOM = 'candle.exe -out $TARGET $SOURCE ${_CANDLEDEFFLAGS}',
54   )
55   env.Append(
56 # Note: Since light.exe is run from $OPEN_DIR, candle.exe must generate
57 # output with paths relative to that dir.
58       SCONS_DIR = '..',  # the scons dir relative to OPEN_DIR
59 # You can change the names of ProductId vars, but NEVER change their values!
60       CANDLEDEFINES = [
61           ('OurWin32ProductId',
62             GGUIDGen('OUR_PRODUCT_ID')),
63           ('OurComponentGUID_FFComponentsDirFiles',
64             GGUIDGen('OUR_COMPONENT_GUID_FF_COMPONENTS_DIR_FILES')),
65           ('OurComponentGUID_FFContentDirFiles',
66             GGUIDGen('OUR_COMPONENT_GUID_FF_CONTENT_DIR_FILES')),
67           ('OurComponentGUID_FFDirFiles',
68             GGUIDGen('OUR_COMPONENT_GUID_FF_DIR_FILES')),
69           ('OurComponentGUID_FFLibDirFiles',
70             GGUIDGen('OUR_COMPONENT_GUID_FF_LIB_DIR_FILES')),
71           ('OurComponentGUID_FFRegistry',
72             GGUIDGen('OUR_COMPONENT_GUID_FF_REGISTRY')),
73           ('OurComponentGUID_IEFiles',
74             GGUIDGen('OUR_COMPONENT_GUID_IE_FILES')),
75           ('OurComponentGUID_IERegistry',
76             GGUIDGen('OUR_COMPONENT_GUID_IE_REGISTRY')),
77           ('OurComponentGUID_SharedFiles',
78             GGUIDGen('OUR_COMPONENT_GUID_SHARED_FILES')),
79           ('OurComponentGUID_SharedVersionedFiles',
80             GGUIDGen('OUR_COMPONENT_GUID_SHARED_VERSIONED_FILES')),
81           ('OurComponentGUID_SharedRegistry',
82             GGUIDGen('OUR_COMPONENT_GUID_SHARED_REGISTRY')),
83           ('OurNpapiProductId',
84             GGUIDGen('OUR_2ND_PRODUCT_ID')),
85           ('OurComponentGUID_NpapiFiles',
86             GGUIDGen('OUR_COMPONENT_GUID_NPAPI_FILES')),
87           ('OurComponentGUID_NpapiRegistry',
88             GGUIDGen('OUR_COMPONENT_GUID_NPAPI_REGISTRY')),
89           ('OurMsiVersion', '$MSI_VERSION'),
90           ('OurCommonPath', '$COMMON_OUTDIR'),
91           ('OurIEPath', '$IE_OUTDIR'),
92           ('OurIpcTestPath', '$COMMON_OUTDIR'),
93           ('OurFFPath', '$INSTALLER_OUTDIR/$INSTALLER_BASENAME'),
94           ('OurNpapiPath', '$NPAPI_OUTDIR'),
95       ]
96   )
97   wix_langs = [re.sub('-', '_', lang) for lang in env['I18N_LANGS']]
98   env.Append(
99       CANDLEDEFINES =
100         [('OurComponentGUID_FFLang' + lang + 'DirFiles',
101            GGUIDGen('OUR_COMPONENT_GUID_FF_' + lang + '_DIR_FILES'))
102          for lang in wix_langs],
103   )
105 def SafeMkdir(dir):
106   """Like the builtin Mkdir, but doesn't fail if the dir exists."""
107   def Func(target, source, env):
108     dir_subst = env.subst(dir, target=target)
109     if not os.path.exists(dir_subst):
110       os.makedirs(dir_subst)
111     return 0
112   return Action(Func, 'SafeMkdir("' + dir + '")')
114 def RecursiveDelete(pattern):
115   """Recursively deletes directories matching a pattern."""
116   def Func(target, source, env):
117     # strip off '.dir' suffix
118     target_dir = env.subst('${TARGET.base}', target=target)
119     for root, dirs, files in os.walk(target_dir):
120       if fnmatch.fnmatch(os.path.normpath(root), pattern):
121         print 'Deleting', root
122         shutil.rmtree(root)
123     return 0
124   return Action(Func, 'RecursiveDelete("' + pattern + '")')
126 def ToUnixPath(path):
127   """Converts windows-style \ to unix-style /."""
128   return re.sub(r'\\', r'/', path)
130 def DirBuilder(env, dirtarget, dirsrcs):
131   """Builder that makes a directory tree by copying source files to
132   corresponding locations inside 'dirtarget'.  'dirsrcs' specifies the list of
133   mappings from source file/directory to the target location.  It's formatted
134   like:
135     (<target file or dir>, <list of source files>)
137   Note: source files that come from an output directory must be explicitly
138   specified relative to the toplevel dir '#'.
139   Note: as shorthand, if the target ends with a '/', then the sources will
140   be placed into that dir.  Otherwise, source is renamed into the target.
141   """
143   srcs = []
144   actions = [Delete('${TARGET.base}')]
145   for target, sources in dirsrcs:
146     target_is_dir = target.endswith('/')
147     if target_is_dir:
148       actions.append(SafeMkdir('${TARGET.base}/' + target))
149     else:
150       actions.append(SafeMkdir('${TARGET.base}/' + os.path.dirname(target)))
151     for source in env.Flatten(sources):
152       source = env.subst(source, conv=lambda x:x)
153       srcs.append(source)
155       # Special-case for Nodes and Node lists: use their absolute paths for
156       # the Copy() action, otherwise it will be relative to our variant dir
157       # (not what Copy expects).
158       if isinstance(source, list): source = source[0]
159       if isinstance(source, SCons.Node.Node): source = source.abspath
161       # HACK: Compensate for the workaround below.  We want the .dir file
162       # to be the dependency to the Command() builder, but we want to copy
163       # the actual directory - so strip the extension here.
164       if source.endswith('.dir'):
165         source = source[:-4]
167       if target_is_dir:
168         actions.append(
169             Copy('${TARGET.base}/' + target + os.path.basename(source),
170                  source))
171       else:
172         actions.append(Copy('${TARGET.base}/' + target, source))
174   # Remove any .svn directories that were copied.
175   actions.append(RecursiveDelete('*/.svn'))
177   # HACK: Workaround for bug in scons where directories aren't checked for
178   # dependency changes.  Instead, we make a temp file the target, and ensure
179   # that that file changes everytime we execute these actions.
180   # See http://scons.tigris.org/issues/show_bug.cgi?id=2261
181   actions += ['$DATE > ${TARGET}']
182   return env.Command(env.subst(dirtarget) + '.dir', srcs, actions)
183 env.AddMethod(DirBuilder)
185 def FirefoxInstaller():
186   dirsrcs = [
187       ('/', ['$FF3_OUTDIR/genfiles/install.rdf',
188              '$FF3_OUTDIR/genfiles/chrome.manifest']),
189       ('lib/', ['$OPEN_DIR/base/firefox/static_files/lib/updater.js']),
190       ('chrome/chromeFiles/content/',
191           GetInputs('$FF3_RESOURCES $COMMON_RESOURCES')),
192       ('chrome/chromeFiles/locale', ['$FF3_OUTDIR/genfiles/i18n']),
193       ('components/',
194           ['$FF3_MODULE_TYPELIB',
195            '$OPEN_DIR/base/firefox/static_files/components/bootstrap.js']),
196       ('components/${SHLIBPREFIX}gears${SHLIBSUFFIX}', ['$FF2_MODULE']),
197       ('components/${SHLIBPREFIX}gears_ff2${SHLIBSUFFIX}', ['$FF3_MODULE']),
198   ]
200   if env['USING_CCTESTS']:
201     dirsrcs += [
202         ('components/', ['$IPC_TEST_EXE']),
203     ]
204   if env['OS'] != 'win32':
205     # TODO(playmobil): Inspector should be located in extensions dir on win32.
206     dirsrcs += [
207         ('resources/inspector', [env.Dir('#/$OPEN_DIR/inspector')]),
208         ('resources/inspector/common/', ['$OPEN_DIR/sdk/gears_init.js',
209                                          '$OPEN_DIR/sdk/samples/sample.js']),
210     ]
211   if env['MODE'] == 'dbg' and env['OS'] in ['win32', 'wince']:
212     dirsrcs += [
213         ('components/gears_ff2.pdb', ['$FF2_MODULE_PDB']),
214         ('components/gears.pdb', ['$FF3_MODULE_PDB']),
215     ]
216   if env['OS'] == 'osx':
217     dirsrcs += [
218         ('resources/', ['$OSX_LAUNCHURL_EXE']),
219     ]
221   dir = env.DirBuilder('$INSTALLER_OUTDIR/$INSTALLER_BASENAME', dirsrcs)
222   actions = [
223       # Mark files writeable to allow .xpi rebuilds
224       'chmod -R 777 ${SOURCE.base}',
225       '(cd ${SOURCE.base} && zip -r ../${TARGET.file} .)'
226   ]
228   return env.Command('$FF_XPI', dir, actions)
229 firefox_installer = FirefoxInstaller()
231 def Win32Installer():
232   wxiobj = env.Command(
233       '$COMMON_GENFILES_DIR/win32_msi.wxiobj',
234       '$COMMON_GENFILES_DIR/win32_msi.wxs',
235       '$CANDLECOM')
236   # TODO(mpcomplete): remove this if/when the notifier goes away.  This
237   # creates fake targets to satisfy the installer build.
238   notifier = env.Command(
239       [
240           '$COMMON_OUTDIR/notifier.exe',
241           '$COMMON_OUTDIR/notifier.dll',
242           '$COMMON_OUTDIR/notifier_test.exe'
243       ], [],
244       'touch $TARGETS')
245   # light.exe must be run from $OPEN_DIR
246   msi = env.Command(
247       '$WIN32_INSTALLER_MSI',
248       [wxiobj, notifier, firefox_installer, '$IE_MODULE', '$NPAPI_MODULE'],
249       'cd $OPEN_DIR && light.exe -out ${TARGET.abspath} ${SOURCES[0].abspath}')
250   return msi
251 win32_installer = Win32Installer()
253 def WinCEInstaller():
254   env['ToUnixPath'] = ToUnixPath
255   inf_outdir = ToUnixPath(env.subst('$IE_OUTDIR'))
256   inf = env.Command(
257       '$COMMON_GENFILES_DIR/wince_cab_fixed.inf',
258       '$COMMON_GENFILES_DIR/wince_cab_ie.inf',
259       'sed -e "s#bin-....wince-arm.ie.#' + inf_outdir + '#g" $SOURCE > $TARGET')
260   cab = env.Command(
261       '$WINCE_INSTALLER_CAB',
262       [inf, '$IE_MODULE', '$IE_WINCE_SETUP_DLL'],
263       ['cabwiz ${ToUnixPath(str(SOURCE))} /compress'
264        ' /err ${SOURCES[0].base}.log',
265        Copy('$TARGET', '${SOURCE.base}.CAB')])
266   return cab
267 wince_installer = WinCEInstaller()
269 def SafariPluginBundle():
270   """This is the actual gears plugin bundle for Safari."""
271   dirsrcs = [
272       ('Contents/', ['$SF_OUTDIR/genfiles/Info.plist']),
273       ('Contents/Resources/English.lproj/InfoPlist.strings',
274           ['$OPEN_DIR/tools/osx/English.lproj/InfoPlist.strings']),
275       ('Contents/Resources/', env.Glob('#/$OPEN_DIR/ui/safari/*.nib')),
276       ('Contents/Resources/', ['$CRASH_SENDER_EXE']),
277       ('Contents/Resources/', ['$OSX_CRASH_INSPECTOR_EXE']),
278       ('Contents/Resources/', ['$OSX_LAUNCHURL_EXE']),
279       ('Contents/MacOS/', ['$SF_MODULE']), 
280   ]
282   if env['USING_CCTESTS']:
283     dirsrcs += [
284         ('Contents/Resources/', ['$IPC_TEST_EXE']),
285     ]
287   return env.DirBuilder('$SF_PLUGIN_BUNDLE', dirsrcs)
288 safari_plugin_bundle = SafariPluginBundle()
290 def SafariPluginProxyBundle():
291   """This is a proxy plugin which simply loads gears into Safari and keeps
292   it in memory. It exists so that gears doesn't unload when Safari wants us
293   to, since that causes crashes."""
294   dirsrcs = [
295       ('Contents/', ['$SF_OUTDIR/genfiles/Info.plist']),
296       ('Contents/MacOS/${SHLIBPREFIX}gears${SHLIBSUFFIX}', ['$SF_PROXY_DLL']),
297       ('Contents/Resources/', [safari_plugin_bundle]),
298       ('Contents/Resources/', ['$OPEN_DIR/tools/osx/uninstall.command']),
299   ]
301   return env.DirBuilder('$SF_PLUGIN_PROXY_BUNDLE', dirsrcs)
302 safari_plugin_proxy_bundle = SafariPluginProxyBundle()
304 def SafariInstallerPluginBundle():
305   dirsrcs = [
306       ('Contents/Info.plist',
307           ['$OPEN_DIR/base/safari/advanced_stats_sheet.plist']),
308       ('Contents/MacOS/InstallerPlugin', ['$SF_INSTALLER_PLUGIN_EXE']),
309       ('Contents/Resources/AdvancedStatsSheet.nib',
310           [env.Dir('#/$OPEN_DIR/base/safari/advanced_stats_sheet.nib')]),
311   ]
313   return env.DirBuilder('$SF_INSTALLER_PLUGIN_BUNDLE', dirsrcs)
314 safari_installer_plugin_bundle = SafariInstallerPluginBundle()
316 def SafariInputManagerBundle():
317   info = env.Command('$SF_OUTDIR/genfiles/Enabler-Info.plist',
318       '$OPEN_DIR/tools/osx/Enabler-Info.plist',
319       'cat $SOURCE |'
320       'sed \'s/$${EXECUTABLE_NAME}/GearsEnabler/\' |'
321       'sed \'s/$${PRODUCT_NAME}/GearsEnabler/\' > $TARGET')
322   dirsrcs = [
323       ('GearsEnabler.bundle/Contents/Info.plist', [info]),
324       ('GearsEnabler.bundle/Contents/MacOS/', ['$SF_INPUTMANAGER_EXE']),
325       ('GearsEnabler.bundle/Contents/Resources/English.lproj/',
326           ['$OPEN_DIR/tools/osx/English.lproj/InfoPlist.strings']),
327       ('Info', ['$OPEN_DIR/tools/osx/Info']),
328   ]
330   return env.DirBuilder('$SF_INPUTMANAGER_BUNDLE', dirsrcs)
331 safari_input_manager_bundle = SafariInputManagerBundle()
333 def SafariInstallerPackage():
334   pkg = env.Iceberg(env.Dir('${SF_INSTALLER_PKG}'),
335       [
336           '$SF_OUTDIR/genfiles/installer.packproj',
337           safari_plugin_proxy_bundle,
338           safari_input_manager_bundle,
339       ])
340   return pkg
341 safari_installer_package = SafariInstallerPackage()
343 def SafariKeystoneInstaller():
344   if not os.path.exists(env.Dir('#/$PRIVATE_DIR').abspath):
345     print 'Skipping Safari Keystone installer. Required sources are not public.'
346     return []
348   env.Append(CREATE_DISK_IMAGE =
349       "/usr/bin/hdiutil create -ov -imagekey zlib-level=9 -fs HFS+"
350       " -format UDZO -volname '$FRIENDLY_NAME ${VERSION}'"
351       " -srcfolder '${INSTALLER_OUTDIR}/Safari/dmg/' -scrub"
352       " -nocrossdev '${SF_KEYSTONE_INSTALLER_DMG}'"
353   )
355   pkg = env.Iceberg(env.Dir('${SF_KEYSTONE_INSTALLER_MPKG}'),
356       ['$SF_OUTDIR/genfiles/keystone_installer.packproj'])
357   env.Depends(pkg, GetInputs('$SF_M4S'))
358   env.Depends(pkg, safari_installer_package)
360   dirsrcs = [
361       ('/', [pkg]),
362       ('/.keystone_install',
363           ['$PRIVATE_DIR/tools/osx/installer/keystone_install']),
364   ]
365   dmg = env.DirBuilder('$INSTALLER_OUTDIR/Safari/dmg', dirsrcs)
366   env.AddPostAction(dmg, 'chmod +x ${TARGET.base}/.keystone_install')
367   # hdiutil is crashy under leopard, so try twice.
368   env.AddPostAction(dmg, '$CREATE_DISK_IMAGE || $CREATE_DISK_IMAGE')
370   return dmg
371 safari_keystone_installer = SafariKeystoneInstaller()
373 installers = []
374 if 'FF3' in env['VALID_BROWSERS']:
375   installers += firefox_installer
376 if 'SF' in env['VALID_BROWSERS']:
377   installers += [
378       safari_input_manager_bundle,
379       safari_plugin_bundle,
380       safari_plugin_proxy_bundle,
381       safari_installer_plugin_bundle,
382       safari_installer_package,
383       safari_input_manager_bundle,
384       safari_keystone_installer,
385   ]
386 if env['OS'] == 'win32':
387   installers += win32_installer
388 if env['OS'] == 'wince':
389   installers += wince_installer
391 env.Alias('gears-installers', installers)