2 # Copyright 2008, Google Inc.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 # Note: If you change this script, make sure the wiki page is up to date:
33 # http://code.google.com/p/nativeclient/wiki/FilesInstalled
36 """Firefox installer for the NaCl developer release
38 A simple script for a NaCl developer to install the Firefox plugin
39 on a machine after a NaCl build from source. To be executed from the
40 root of the NaCl source tree.
52 # Is this script embedded in an installer?
53 # Set with a command line option (e.g. PKGINSTALL).
59 %s PLATFORM_BASE=<platform_base>
61 You don't usually invoke this script directly.
62 Instead, you use SCons, with the following syntax:
63 ./scons [--prebuilt] firefox_install [DBG=1]
65 --prebuilt means don't attempt to rebuild the plugin binaries
66 DBG=1 means install the debug version of the plugin
68 %s PLATFORM_BASE=.../native_client/scons-out/
70 ./scons --prebuilt firefox_install
72 Note: by default the scons command will install the release version
73 of the plugin. In order to install the debug version, use:
74 ./scons --prebuilt firefox_install DBG=1
76 %s PLATFORM_BASE=.../native_client/scons-out/ MODE=1
78 In this case scons will take care of the command line args.
79 """ % (progname
, progname
, progname
))
84 sys
.stderr
.write("\n**** INSTALLATION FAILED.\n\n")
87 def CheckCondition(boolcond
, emsg
):
89 FatalError("Error:" + emsg
+ "\n")
91 def CheckFileExists(what
, emsg
):
92 if os
.path
.isfile(what
): return
93 FatalError("Error: \"%s\" not found.\n%s\n" % (what
, emsg
))
95 def CheckDirExists(what
, emsg
):
96 if os
.path
.isdir(what
): return
97 FatalError("Error: directory \"%s\" not found.\n%s\n" % (what
, emsg
))
100 # Can't be interactive if embedded.
103 sys
.stdout
.write("Okay to continue? [y/n] ")
104 answer
= sys
.stdin
.readline()
106 print "Okay, you asked for it."
109 print "Okay, I'm bailing out then."
112 def CopyFile(src
, dst
):
114 print "copying", src
, "to", dst
, "..."
115 if os
.path
.isfile(dst
): os
.unlink(dst
)
116 shutil
.copy2(src
, dst
)
118 FatalError("ERROR: Could not copy %s to %s\n" % (src
, dst
))
120 def CopyDir(src
, dst
):
122 print "copying directory", src
, "to", dst
, "..."
123 shutil
.copytree(src
, dst
)
125 FatalError("ERROR: Could not copy %s to %s: %s\n" % (src
, dst
, err
))
127 def CopyFilesOrDirs(src_dir
, dst_dir
, list):
129 name
= os
.path
.join(src_dir
, f
)
130 if os
.path
.isfile(name
):
131 CopyFile(name
, dst_dir
)
132 if os
.path
.isdir(name
):
133 CopyDir(name
, dst_dir
)
137 print "[Removing", dir, "...]"
140 FatalError("ERROR: Could not remove %s\n" % (dir))
142 def TryMakedir(dirname
):
143 if not os
.path
.isdir(dirname
):
145 print "[Creating", dirname
, "...]"
148 FatalError("ERROR: Could not create %s\n" % dirname
)
150 def RemoveFile(fname
):
152 print "[Removing", fname
, "...]"
155 FatalError("ERROR: Could not remove %s\n" % fname
)
157 def RemoveFilesOrDirs(dir, list):
159 name
= os
.path
.join(dir, f
)
160 if os
.path
.isfile(name
):
162 if os
.path
.isdir(name
):
165 def GetFromStaging(PLATFORM_BASE
, what
):
166 # Try local version in case we're an installer and all is "right here!"
168 localversion
= os
.path
.join(PLATFORM_BASE
, what
)
169 if os
.path
.exists(localversion
):
171 return os
.path
.join(PLATFORM_BASE
, "staging", what
)
174 print "*********************************************************************"
178 if pl
in ['linux', 'linux2']:
179 return os
.path
.expandvars("$HOME/.mozilla/plugins")
180 if pl
in ['darwin', 'mac']:
181 return os
.path
.expanduser(os
.path
.join("~", "Library", "Internet Plug-Ins"))
182 elif pl
in ['win32', 'cygwin', 'win', 'windows']:
183 return os
.path
.join(os
.getenv('PROGRAMFILES'), "Mozilla Firefox", "plugins")
185 FatalError("Unknown platform %s" % pl
)
187 def GetFilesToCopy():
189 if pl
in ['linux', 'linux2']:
190 return ["libnpGoogleNaClPlugin.so", "sel_ldr", "sel_ldr_bin", "sel_mon", "sel_ldr_bin.trace"]
191 if pl
in ['darwin', 'mac']:
192 return ["npGoogleNaClPlugin.bundle"]
193 elif pl
in ['win32', 'cygwin', 'win', 'windows']:
194 return ["npGoogleNaClPlugin.dll", "sel_ldr.exe"]
196 FatalError("Unknown platform %s" % pl
)
198 def InstallSuccess(sel_ldr
):
200 print "* You have successfully installed the NaCl Firefox plugin."
201 print "* As a self-test, please confirm you can run"
203 print "* from a shell/command prompt. With no args you should see"
204 print "* No nacl file specified"
205 print "* on Linux or Mac and no output on Windows."
208 def RunningOn64BitSystem():
209 if (8 == len(struct
.pack('P',0))):
213 def Linux_install(PLATFORM_BASE
):
214 PLUGINDIR
= GetPluginDir()
215 PLUGIN
= os
.path
.join(PLATFORM_BASE
, "staging", "libnpGoogleNaClPlugin.so")
216 SEL_LDR
= GetFromStaging(PLATFORM_BASE
, "sel_ldr")
217 SEL_LDR_SANDBOX
= GetFromStaging(PLATFORM_BASE
, "sel_ldr.trace")
218 SEL_LDR_SH
= os
.path
.join(PLATFORM_BASE
, "../../tools/sel_ldr.bash")
219 LIBSDL
= GetFromStaging(PLATFORM_BASE
, "libSDL-1.2.so.0")
220 SEL_LDR_INSTALLED_AS
= os
.path
.join(PLUGINDIR
, "sel_ldr_bin")
221 SEL_LDR_SH_INSTALLED_AS
= os
.path
.join(PLUGINDIR
, "sel_ldr")
222 SEL_LDR_SANDBOX_INSTALLED_AS
= os
.path
.join(PLUGINDIR
, "sel_ldr_bin.trace")
223 SDL_INSTALLED_AS
= os
.path
.join(PLUGINDIR
, "libSDL-1.2.so.0")
224 SEL_MON
= GetFromStaging(PLATFORM_BASE
, "sel_mon")
226 # Check that all source and destination files/directories exist
227 CheckFileExists(SEL_LDR
, "Have you built NaCl yet?")
228 CheckFileExists(PLUGIN
, "Have you built NaCl yet?")
229 CheckFileExists(LIBSDL
, "Have you built NaCl yet?")
230 CheckFileExists("/bin/bash", "No /bin/bash? NaCl needs this to launch sel_ldr")
232 # Tell the user what we're going to do
233 print "This script will install"
234 print PLUGIN
, ",", LIBSDL
, "and", SEL_LDR
, "in", PLUGINDIR
235 if not OkayToInstall():
239 TryMakedir(PLUGINDIR
)
240 CopyFile(PLUGIN
, PLUGINDIR
)
241 if RunningOn64BitSystem():
242 # Call the wrapper on 64-bit Linux
243 print '64bit system detected running nspluginwrapper'
244 cmd
= 'nspluginwrapper -i %s' % os
.path
.join(PLUGINDIR
,
245 os
.path
.basename(PLUGIN
))
248 CopyFile(SEL_MON
, PLUGINDIR
)
249 # avoid installing libSDL twice
250 if not os
.path
.isfile(SDL_INSTALLED_AS
):
251 CopyFile(LIBSDL
, SDL_INSTALLED_AS
)
252 CopyFile(SEL_LDR
, SEL_LDR_INSTALLED_AS
)
253 CopyFile(SEL_LDR_SH
, SEL_LDR_SH_INSTALLED_AS
)
254 CopyFile(SEL_LDR_SANDBOX
, SEL_LDR_SANDBOX_INSTALLED_AS
)
255 os
.chmod(SEL_LDR_SH_INSTALLED_AS
, stat
.S_IRUSR | stat
.S_IXUSR | stat
.S_IWUSR
)
256 InstallSuccess(os
.path
.join(PLUGINDIR
, "sel_ldr"))
258 def Windows_install(PLATFORM_BASE
):
259 PLUGINDIR
= GetPluginDir()
260 SEL_LDR
= GetFromStaging(PLATFORM_BASE
, "sel_ldr.exe")
261 SDL_DLL
= GetFromStaging(PLATFORM_BASE
, "SDL.dll")
262 PLUGIN
= os
.path
.join(PLATFORM_BASE
, "staging", "npGoogleNaClPlugin.dll")
264 # Check that all source and destination files/directories exist
265 CheckFileExists(SEL_LDR
, "Have you built NaCl yet?")
266 CheckFileExists(SDL_DLL
, "Have you built NaCl yet?")
267 CheckFileExists(PLUGIN
, "Have you built NaCl yet?")
268 CheckDirExists(PLUGINDIR
, "I don't know where to install browser plugins.")
270 # Tell the user what we're going to do
271 print "This script will install"
272 print PLUGIN
, ",", SEL_LDR
, "and", SDL_DLL
273 print "in", PLUGINDIR
274 if not OkayToInstall():
278 TryMakedir(PLUGINDIR
)
279 CopyFile(SEL_LDR
, PLUGINDIR
)
280 CopyFile(SDL_DLL
, PLUGINDIR
)
281 CopyFile(PLUGIN
, PLUGINDIR
)
282 InstallSuccess(os
.path
.join(PLUGINDIR
, "sel_ldr.exe"))
284 def MacNeedsSDL(SDLDEST
):
286 if os
.path
.isdir("/Library/Frameworks/SDL.framework"):
287 SDLPath
= "/Library/Frameworks/SDL.framework"
288 elif os
.path
.isdir(SDLDEST
):
294 print "* It looks like SDL is already installed as"
296 print "* For Native Client we recommend SDL Version 1.2.13"
297 print "* Please make sure your SDL version is compatible"
298 print "* with Native Client."
303 def Mac_install(PLATFORM_BASE
):
304 PLUGINDIR
= GetPluginDir()
305 BUNDLEDIR
= os
.path
.join(PLUGINDIR
, "npGoogleNaClPlugin.bundle")
306 SEL_LDR
= GetFromStaging(PLATFORM_BASE
, "sel_ldr")
308 # Local versions in case we're running in an installer (not from the
309 # source tree) and everything is in one spot
312 localversion
= os
.path
.join(PLATFORM_BASE
, "npGoogleNaClPlugin.bundle")
313 if os
.path
.exists(localversion
):
314 BUNDLE
= localversion
316 BUNDLE
= os
.path
.join(PLATFORM_BASE
, "staging", "npGoogleNaClPlugin.bundle")
320 localversion
= os
.path
.join(PLATFORM_BASE
, "SDL.framework")
321 if os
.path
.exists(localversion
):
322 SDLFRAMEWORK
= localversion
324 SDLFRAMEWORK
= os
.path
.join(PLATFORM_BASE
, "Frameworks", "SDL.framework")
325 FRAMEWORKS
= os
.path
.expanduser(os
.path
.join("~", "Library", "Frameworks"))
326 SDLDEST
= os
.path
.join(FRAMEWORKS
, "SDL.framework")
327 SEL_LDR_DIR
= os
.path
.join(BUNDLEDIR
, "Contents", "Resources")
329 # Check that all source and destination files/directories exist
330 CheckDirExists(BUNDLE
, "Have you built NaCl yet?")
331 CheckDirExists(SDLFRAMEWORK
, "Have you built NaCl yet?")
332 CheckFileExists(os
.path
.join(BUNDLE
,
333 "Contents", "MacOS", "npGoogleNaClPlugin"),
334 "Have you built NaCl yet?")
335 CheckFileExists(SEL_LDR
, "Have you built NaCl yet?")
336 TryMakedir(PLUGINDIR
)
338 # Tell the user what we're going to do
339 print "This script will install:"
340 print " ", BUNDLE
, "in", BUNDLEDIR
341 print " ", SEL_LDR
, "in", SEL_LDR_DIR
343 print SDLFRAMEWORK
, "in", SDLDEST
344 if not OkayToInstall():
348 if os
.path
.isdir(BUNDLEDIR
):
351 CopyDir(BUNDLE
, BUNDLEDIR
)
352 if MacNeedsSDL(SDLDEST
):
353 if not os
.path
.isdir(FRAMEWORKS
):
354 os
.makedirs(FRAMEWORKS
)
355 CopyDir(SDLFRAMEWORK
, SDLDEST
)
356 CopyFile(SEL_LDR
, SEL_LDR_DIR
)
357 InstallSuccess(os
.path
.join(SEL_LDR_DIR
, "sel_ldr"))
362 if (arg
.find("=") < 0):
364 name
, value
= arg
.split("=")
365 print("%s=%s" % (name
, value
))
367 # require PLATFORM_BASE (or PKGINSTALL) to be set
368 if ("PLATFORM_BASE" not in args
and "PKGINSTALL" not in args
369 and "BACKUP" not in args
and "RESTORE" not in args
):
371 if "PKGINSTALL" in args
:
374 if "MODE" not in args
: args
["MODE"] = '0'
375 if "BACKUP" not in args
: args
["BACKUP"] = '0'
376 if "RESTORE" not in args
: args
["RESTORE"] = '0'
379 def GetTmpDirectory():
381 if pl
in ['linux', 'linux2', 'darwin', 'mac']:
382 tmp_dir
= '/tmp/nacl'
383 elif pl
in ['win32', 'cygwin', 'win', 'windows']:
384 os_tmp
= os
.getenv('TMP')
385 tmp_dir
= os
.path
.join(os_tmp
, 'nacl')
387 FatalError("Backup/Restore cannot continue. Unknown platform %s" % pl
)
391 tmp_dir
= GetTmpDirectory()
392 plugin_dir
= GetPluginDir()
393 files_to_copy
= GetFilesToCopy()
395 if os
.path
.isdir(tmp_dir
):
396 RemoveFilesOrDirs(tmp_dir
, files_to_copy
)
398 # If for some reason there is a file with the same name.
399 if os
.path
.isfile(tmp_dir
):
403 if os
.path
.exists(plugin_dir
):
404 CopyFilesOrDirs(plugin_dir
, tmp_dir
, files_to_copy
)
407 tmp_dir
= GetTmpDirectory()
408 plugin_dir
= GetPluginDir()
409 files_to_copy
= GetFilesToCopy()
411 if os
.path
.exists(plugin_dir
):
412 RemoveFilesOrDirs(plugin_dir
, files_to_copy
)
414 if os
.path
.exists(tmp_dir
):
415 CopyFilesOrDirs(tmp_dir
, plugin_dir
, files_to_copy
)
416 RemoveFilesOrDirs(tmp_dir
, files_to_copy
)
419 args
= ParseArgv(argv
)
424 if args
["BACKUP"] == '1':
428 if args
["RESTORE"] == '1':
432 if args
["MODE"] == '1':
438 if pl
in ['linux', 'linux2']:
439 Linux_install(args
["PLATFORM_BASE"] + mode
+ 'linux')
440 elif pl
in ['win32', 'cygwin', 'win', 'windows']:
441 Windows_install(args
["PLATFORM_BASE"] + mode
+ 'win')
442 elif pl
in ['darwin', 'mac']:
443 if os
.uname()[-1] != 'i386':
444 FatalError('Cannot install on PPC Macs.')
445 if "PKGINSTALL" in args
:
446 Mac_install(args
["PKGINSTALL"])
448 Mac_install(args
["PLATFORM_BASE"] + mode
+ 'mac')
450 print "Install cannot continue. Unknown platform %s" % pl
454 PLUGINDEMO
= os
.path
.join("scons-out", "nacl", "staging", "index.html")
455 print "* To test this installation also try the test links on the page"
456 print "* ", PLUGINDEMO
460 if '__main__' == __name__
:
461 sys
.exit(main(sys
.argv
))