1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/b2g/simulator/build_xpi.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,147 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +# Generate xpi for the simulator addon by: 1.9 +# - building a special gaia profile for it, as we need: 1.10 +# * more languages, and, 1.11 +# * less apps 1.12 +# than b2g desktop's one 1.13 +# - retrieve usefull app version metadata from the build system 1.14 +# - finally, use addon sdk's cfx tool to build the addon xpi 1.15 +# that ships: 1.16 +# * a small firefox addon registering to the app manager 1.17 +# * b2g desktop runtime 1.18 +# * gaia profile 1.19 + 1.20 +import sys, os, re, subprocess 1.21 +from mozbuild.preprocessor import Preprocessor 1.22 +from mozbuild.base import MozbuildObject 1.23 +from mozbuild.util import ensureParentDir 1.24 +from zipfile import ZipFile 1.25 +from distutils.version import LooseVersion 1.26 + 1.27 +ftp_root_path = "/pub/mozilla.org/labs/fxos-simulator" 1.28 +UPDATE_LINK = "https://ftp.mozilla.org" + ftp_root_path + "/%(update_path)s/%(xpi_name)s" 1.29 +UPDATE_URL = "https://ftp.mozilla.org" + ftp_root_path + "/%(update_path)s/update.rdf" 1.30 +XPI_NAME = "fxos-simulator-%(version)s-%(platform)s.xpi" 1.31 + 1.32 +class GaiaBuilder(object): 1.33 + def __init__(self, build, gaia_path): 1.34 + self.build = build 1.35 + self.gaia_path = gaia_path 1.36 + 1.37 + def clean(self): 1.38 + self.build._run_make(target="clean", directory=self.gaia_path) 1.39 + 1.40 + def profile(self, env): 1.41 + self.build._run_make(target="profile", directory=self.gaia_path, num_jobs=1, silent=False, append_env=env) 1.42 + 1.43 + def override_prefs(self, srcfile): 1.44 + # Note that each time we call `make profile` in gaia, a fresh new pref file is created 1.45 + # cat srcfile >> profile/user.js 1.46 + with open(os.path.join(self.gaia_path, "profile", "user.js"), "a") as userJs: 1.47 + userJs.write(open(srcfile).read()) 1.48 + 1.49 +def process_package_overload(src, dst, version, app_buildid): 1.50 + ensureParentDir(dst) 1.51 + # First replace numeric version like '1.3' 1.52 + # Then replace with 'slashed' version like '1_4' 1.53 + # Finally set the full length addon version like 1.3.20131230 1.54 + # (reduce the app build id to only the build date 1.55 + # as addon manager doesn't handle big ints in addon versions) 1.56 + defines = { 1.57 + "NUM_VERSION": version, 1.58 + "SLASH_VERSION": version.replace(".", "_"), 1.59 + "FULL_VERSION": ("%s.%s" % (version, app_buildid[:8])) 1.60 + } 1.61 + pp = Preprocessor(defines=defines) 1.62 + pp.do_filter("substitution") 1.63 + with open(dst, "w") as output: 1.64 + with open(src, "r") as input: 1.65 + pp.processFile(input=input, output=output) 1.66 + 1.67 +def add_dir_to_zip(zip, top, pathInZip, blacklist=()): 1.68 + zf = ZipFile(zip, "a") 1.69 + for dirpath, subdirs, files in os.walk(top): 1.70 + dir_relpath = os.path.relpath(dirpath, top) 1.71 + if dir_relpath.startswith(blacklist): 1.72 + continue 1.73 + zf.write(dirpath, os.path.join(pathInZip, dir_relpath)) 1.74 + for filename in files: 1.75 + relpath = os.path.join(dir_relpath, filename) 1.76 + if relpath in blacklist: 1.77 + continue 1.78 + zf.write(os.path.join(dirpath, filename), 1.79 + os.path.join(pathInZip, relpath)) 1.80 + zf.close() 1.81 + 1.82 +def main(platform): 1.83 + build = MozbuildObject.from_environment() 1.84 + topsrcdir = build.topsrcdir 1.85 + distdir = build.distdir 1.86 + 1.87 + srcdir = os.path.join(topsrcdir, "b2g", "simulator") 1.88 + 1.89 + app_buildid = open(os.path.join(build.topobjdir, "config", "buildid")).read().strip() 1.90 + 1.91 + # The simulator uses a shorter version string, 1.92 + # it only keeps the major version digits A.B 1.93 + # whereas MOZ_B2G_VERSION is A.B.C.D 1.94 + b2g_version = build.config_environment.defines["MOZ_B2G_VERSION"].replace('"', '') 1.95 + version = ".".join(str(n) for n in LooseVersion(b2g_version).version[0:2]) 1.96 + 1.97 + # Build a gaia profile specific to the simulator in order to: 1.98 + # - disable the FTU 1.99 + # - set custom prefs to enable devtools debugger server 1.100 + # - set custom settings to disable lockscreen and screen timeout 1.101 + # - only ship production apps 1.102 + gaia_path = build.config_environment.substs["GAIADIR"] 1.103 + builder = GaiaBuilder(build, gaia_path) 1.104 + builder.clean() 1.105 + env = { 1.106 + "NOFTU": "1", 1.107 + "GAIA_APP_TARGET": "production", 1.108 + "SETTINGS_PATH": os.path.join(srcdir, "custom-settings.json") 1.109 + } 1.110 + builder.profile(env) 1.111 + builder.override_prefs(os.path.join(srcdir, "custom-prefs.js")) 1.112 + 1.113 + # Substitute version strings in the package manifest overload file 1.114 + manifest_overload = os.path.join(build.topobjdir, "b2g", "simulator", "package-overload.json") 1.115 + process_package_overload(os.path.join(srcdir, "package-overload.json.in"), 1.116 + manifest_overload, 1.117 + version, 1.118 + app_buildid) 1.119 + 1.120 + # Build the simulator addon xpi 1.121 + xpi_name = XPI_NAME % {"version": version, "platform": platform} 1.122 + xpi_path = os.path.join(distdir, xpi_name) 1.123 + 1.124 + update_path = "%s/%s" % (version, platform) 1.125 + update_link = UPDATE_LINK % {"update_path": update_path, "xpi_name": xpi_name} 1.126 + update_url = UPDATE_URL % {"update_path": update_path} 1.127 + subprocess.check_call([ 1.128 + build.virtualenv_manager.python_path, os.path.join(topsrcdir, "addon-sdk", "source", "bin", "cfx"), "xpi", \ 1.129 + "--pkgdir", srcdir, \ 1.130 + "--manifest-overload", manifest_overload, \ 1.131 + "--strip-sdk", \ 1.132 + "--update-link", update_link, \ 1.133 + "--update-url", update_url, \ 1.134 + "--static-args", "{\"label\": \"Firefox OS %s\"}" % version, \ 1.135 + "--output-file", xpi_path \ 1.136 + ]) 1.137 + 1.138 + # Ship b2g-desktop, but prevent its gaia profile to be shipped in the xpi 1.139 + add_dir_to_zip(xpi_path, os.path.join(distdir, "b2g"), "b2g", ("gaia", "B2G.app/Contents/MacOS/gaia")) 1.140 + # Then ship our own gaia profile 1.141 + add_dir_to_zip(xpi_path, os.path.join(gaia_path, "profile"), "profile") 1.142 + 1.143 +if __name__ == '__main__': 1.144 + if 2 != len(sys.argv): 1.145 + print("""Usage: 1.146 + python {0} MOZ_PKG_PLATFORM 1.147 +""".format(sys.argv[0])) 1.148 + sys.exit(1) 1.149 + main(*sys.argv[1:]) 1.150 +