Exemple #1
0
    def clean_nightlies(self, force=False, keep=None):
        self.set_use_stable_rust(False)
        rust_current_nightly = self.rust_version()
        self.set_use_stable_rust(True)
        rust_current_stable = self.rust_version()
        cargo_current = self.cargo_build_id()
        print("Current Rust nightly version: {}".format(rust_current_nightly))
        print("Current Rust stable version: {}".format(rust_current_stable))
        print("Current Cargo version: {}".format(cargo_current))
        to_keep = {
            'rust': set(),
            'cargo': set(),
        }
        if int(keep) == 1:
            # Optimize keep=1 case to not invoke git
            to_keep['rust'].add(rust_current_nightly)
            to_keep['rust'].add(rust_current_stable)
            to_keep['cargo'].add(cargo_current)
        else:
            for tool, version_files in {
                    'rust': ['rust-commit-hash', 'rust-stable-version'],
                    'cargo': ['cargo-commit-hash'],
            }.items():
                for version_file in version_files:
                    cmd = subprocess.Popen([
                        'git', 'log', '--oneline', '--no-color', '-n', keep,
                        '--patch', version_file
                    ],
                                           stdout=subprocess.PIPE,
                                           universal_newlines=True)
                    stdout, _ = cmd.communicate()
                    for line in stdout.splitlines():
                        if line.startswith(
                                b"+") and not line.startswith(b"+++"):
                            to_keep[tool].add(line[1:])

        removing_anything = False
        for tool in ["rust", "cargo"]:
            base = path.join(self.context.sharedir, tool)
            if not path.isdir(base):
                continue
            for name in os.listdir(base):
                # We append `-alt` if LLVM assertions aren't enabled,
                # so use just the commit hash itself.
                # This may occasionally leave an extra nightly behind
                # but won't remove too many nightlies.
                if name.partition('-')[0] not in to_keep[tool]:
                    removing_anything = True
                    full_path = path.join(base, name)
                    if force:
                        print("Removing {}".format(full_path))
                        delete(full_path)
                    else:
                        print("Would remove {}".format(full_path))
        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("Nothing done. "
                  "Run `./mach clean-nightlies -f` to actually remove.")
    def clean_nightlies(self, force=False, keep=None):
        self.set_use_stable_rust(False)
        rust_current_nightly = self.rust_version()
        self.set_use_stable_rust(True)
        rust_current_stable = self.rust_version()
        cargo_current = self.cargo_build_id()
        print("Current Rust nightly version: {}".format(rust_current_nightly))
        print("Current Rust stable version: {}".format(rust_current_stable))
        print("Current Cargo version: {}".format(cargo_current))
        to_keep = {
            'rust': set(),
            'cargo': set(),
        }
        if int(keep) == 1:
            # Optimize keep=1 case to not invoke git
            to_keep['rust'].add(rust_current_nightly)
            to_keep['rust'].add(rust_current_stable)
            to_keep['cargo'].add(cargo_current)
        else:
            for tool, version_files in {
                'rust': ['rust-commit-hash', 'rust-stable-version'],
                'cargo': ['cargo-commit-hash'],
            }.items():
                for version_file in version_files:
                    cmd = subprocess.Popen(
                        ['git', 'log', '--oneline', '--no-color', '-n', keep, '--patch', version_file],
                        stdout=subprocess.PIPE,
                        universal_newlines=True
                    )
                    stdout, _ = cmd.communicate()
                    for line in stdout.splitlines():
                        if line.startswith(b"+") and not line.startswith(b"+++"):
                            to_keep[tool].add(line[1:])

        removing_anything = False
        for tool in ["rust", "cargo"]:
            base = path.join(self.context.sharedir, tool)
            if not path.isdir(base):
                continue
            for name in os.listdir(base):
                # We append `-alt` if LLVM assertions aren't enabled,
                # so use just the commit hash itself.
                # This may occasionally leave an extra nightly behind
                # but won't remove too many nightlies.
                if name.partition('-')[0] not in to_keep[tool]:
                    removing_anything = True
                    full_path = path.join(base, name)
                    if force:
                        print("Removing {}".format(full_path))
                        delete(full_path)
                    else:
                        print("Would remove {}".format(full_path))
        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("Nothing done. "
                  "Run `./mach clean-nightlies -f` to actually remove.")
    def clean_nightlies(self, force=False, keep=None):
        rust_current = self.rust_version()
        cargo_current = self.cargo_build_id()
        print("Current Rust version: {}".format(rust_current))
        print("Current Cargo version: {}".format(cargo_current))
        to_keep = {
            'rust': set(),
            'cargo': set(),
        }
        if int(keep) == 1:
            # Optimize keep=1 case to not invoke git
            to_keep['rust'].add(rust_current)
            to_keep['cargo'].add(cargo_current)
        else:
            for tool in ["rust", "cargo"]:
                commit_file = '{}-commit-hash'.format(tool)
                cmd = subprocess.Popen(
                    ['git', 'log', '--pretty=format:%H', '-n', keep, commit_file],
                    stdout=subprocess.PIPE,
                    universal_newlines=True
                )
                stdout, _ = cmd.communicate()
                for commit in stdout.splitlines():
                    cmd = subprocess.Popen(
                        ['git', 'show', '{}:{}'.format(commit, commit_file)],
                        stdout=subprocess.PIPE,
                        universal_newlines=True
                    )
                    commit_hash, _ = cmd.communicate()
                    to_keep[tool].add(commit_hash.rstrip())

        removing_anything = False
        for tool in ["rust", "cargo"]:
            base = path.join(self.context.sharedir, tool)
            for name in os.listdir(base):
                # We append `-alt` if LLVM assertions aren't enabled,
                # so use just the commit hash itself.
                # This may occasionally leave an extra nightly behind
                # but won't remove too many nightlies.
                if name.partition('-')[0] not in to_keep[tool]:
                    removing_anything = True
                    full_path = path.join(base, name)
                    if force:
                        print("Removing {}".format(full_path))
                        delete(full_path)
                    else:
                        print("Would remove {}".format(full_path))
        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("Nothing done. "
                  "Run `./mach clean-nightlies -f` to actually remove.")
    def clean_nightlies(self, force=False, keep=None):
        rust_current_nightly = self.rust_nightly_date()
        rust_current_stable = self.rust_stable_version()
        print("Current Rust nightly version: {}".format(rust_current_nightly))
        print("Current Rust stable version: {}".format(rust_current_stable))
        to_keep = set()
        if int(keep) == 1:
            # Optimize keep=1 case to not invoke git
            to_keep.add(rust_current_nightly)
            to_keep.add(rust_current_stable)
        else:
            for version_file in ['rust-toolchain', 'rust-stable-version']:
                cmd = subprocess.Popen([
                    'git', 'log', '--oneline', '--no-color', '-n', keep,
                    '--patch', version_file
                ],
                                       stdout=subprocess.PIPE,
                                       universal_newlines=True)
                stdout, _ = cmd.communicate()
                for line in stdout.splitlines():
                    if line.startswith(b"+") and not line.startswith(b"+++"):
                        line = line[len(b"+"):]
                        if line.startswith(b"nightly-"):
                            line = line[len(b"nightly-"):]
                        to_keep.add(line)

        removing_anything = False
        for tool in ["rust", "cargo"]:
            base = path.join(self.context.sharedir, tool)
            if not path.isdir(base):
                continue
            for name in os.listdir(base):
                full_path = path.join(base, name)
                if name.startswith("rust-"):
                    name = name[len("rust-"):]
                if name.endswith("-alt"):
                    name = name[:-len("-alt")]
                if name not in to_keep:
                    removing_anything = True
                    if force:
                        print("Removing {}".format(full_path))
                        try:
                            delete(full_path)
                        except OSError as e:
                            print("Removal failed with error {}".format(e))
                    else:
                        print("Would remove {}".format(full_path))
        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("Nothing done. "
                  "Run `./mach clean-nightlies -f` to actually remove.")
Exemple #5
0
    def clean_nightlies(self, force=False, keep=None):
        rust_current_nightly = self.rust_nightly_date()
        rust_current_stable = self.rust_stable_version()
        print("Current Rust nightly version: {}".format(rust_current_nightly))
        print("Current Rust stable version: {}".format(rust_current_stable))
        to_keep = set()
        if int(keep) == 1:
            # Optimize keep=1 case to not invoke git
            to_keep.add(rust_current_nightly)
            to_keep.add(rust_current_stable)
        else:
            for version_file in ['rust-toolchain', 'rust-stable-version']:
                cmd = subprocess.Popen(
                    ['git', 'log', '--oneline', '--no-color', '-n', keep, '--patch', version_file],
                    stdout=subprocess.PIPE,
                    universal_newlines=True
                )
                stdout, _ = cmd.communicate()
                for line in stdout.splitlines():
                    if line.startswith(b"+") and not line.startswith(b"+++"):
                        line = line[len(b"+"):]
                        if line.startswith(b"nightly-"):
                            line = line[len(b"nightly-"):]
                        to_keep.add(line)

        removing_anything = False
        for tool in ["rust", "cargo"]:
            base = path.join(self.context.sharedir, tool)
            if not path.isdir(base):
                continue
            for name in os.listdir(base):
                full_path = path.join(base, name)
                if name.startswith("rust-"):
                    name = name[len("rust-"):]
                if name.endswith("-alt"):
                    name = name[:-len("-alt")]
                if name not in to_keep:
                    removing_anything = True
                    if force:
                        print("Removing {}".format(full_path))
                        try:
                            delete(full_path)
                        except OSError as e:
                            print("Removal failed with error {}".format(e))
                    else:
                        print("Would remove {}".format(full_path))
        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("Nothing done. "
                  "Run `./mach clean-nightlies -f` to actually remove.")
Exemple #6
0
def change_prefs(resources_path, platform):
    print("Swapping prefs")
    prefs_path = path.join(resources_path, "prefs.json")
    package_prefs_path = path.join(resources_path, "package-prefs.json")
    os_type = "os:{}".format(platform)
    with open(prefs_path) as prefs, open(package_prefs_path) as package_prefs:
        prefs = json.load(prefs)
        package_prefs = json.load(package_prefs)
        for pref in package_prefs:
            if os_type in pref:
                prefs[pref.split(";")[1]] = package_prefs[pref]
            if pref in prefs:
                prefs[pref] = package_prefs[pref]
        with open(prefs_path, "w") as out:
            json.dump(prefs, out, sort_keys=True, indent=2)
    delete(package_prefs_path)
Exemple #7
0
def change_prefs(resources_path, platform, vr=False):
    print("Swapping prefs")
    prefs_path = path.join(resources_path, "prefs.json")
    package_prefs_path = path.join(resources_path, "package-prefs.json")
    with open(prefs_path) as prefs, open(package_prefs_path) as package_prefs:
        prefs = json.load(prefs)
        pref_sets = []
        package_prefs = json.load(package_prefs)
        if "all" in package_prefs:
            pref_sets += [package_prefs["all"]]
        if vr and "vr" in package_prefs:
            pref_sets += [package_prefs["vr"]]
        if platform in package_prefs:
            pref_sets += [package_prefs[platform]]
        for pref_set in pref_sets:
            for pref in pref_set:
                if pref in prefs:
                    prefs[pref] = pref_set[pref]
        with open(prefs_path, "w") as out:
            json.dump(prefs, out, sort_keys=True, indent=2)
    delete(package_prefs_path)
Exemple #8
0
def change_prefs(resources_path, platform, vr=False):
    print("Swapping prefs")
    prefs_path = path.join(resources_path, "prefs.json")
    package_prefs_path = path.join(resources_path, "package-prefs.json")
    with open(prefs_path) as prefs, open(package_prefs_path) as package_prefs:
        prefs = json.load(prefs)
        pref_sets = []
        package_prefs = json.load(package_prefs)
        if "all" in package_prefs:
            pref_sets += [package_prefs["all"]]
        if vr and "vr" in package_prefs:
            pref_sets += [package_prefs["vr"]]
        if platform in package_prefs:
            pref_sets += [package_prefs[platform]]
        for pref_set in pref_sets:
            for pref in pref_set:
                if pref in prefs:
                    prefs[pref] = pref_set[pref]
        with open(prefs_path, "w") as out:
            json.dump(prefs, out, sort_keys=True, indent=2)
    delete(package_prefs_path)
Exemple #9
0
    def package(self, release=False, dev=False, android=None, magicleap=None, debug=False,
                debugger=None, target=None, flavor=None, maven=False):
        if android is None:
            android = self.config["build"]["android"]
        if target and android:
            print("Please specify either --target or --android.")
            sys.exit(1)
        if not android:
            android = self.handle_android_target(target)
        else:
            target = self.config["android"]["target"]
        if target and magicleap:
            print("Please specify either --target or --magicleap.")
            sys.exit(1)
        if magicleap:
            target = "aarch64-linux-android"
        env = self.build_env(target=target)
        binary_path = self.get_binary_path(release, dev, android=android, magicleap=magicleap)
        dir_to_root = self.get_top_dir()
        target_dir = path.dirname(binary_path)
        if magicleap:
            if platform.system() not in ["Darwin"]:
                raise Exception("Magic Leap builds are only supported on macOS.")
            if not env.get("MAGICLEAP_SDK"):
                raise Exception("Magic Leap builds need the MAGICLEAP_SDK environment variable")
            if not env.get("MLCERT"):
                raise Exception("Magic Leap builds need the MLCERT environment variable")
            mabu = path.join(env.get("MAGICLEAP_SDK"), "mabu")
            package = "./support/magicleap/Servo2D/Servo2D.package"
            if dev:
                build_type = "lumin_debug"
            else:
                build_type = "lumin_release"
            argv = [
                mabu,
                "-o", target_dir,
                "-t", build_type,
                package
            ]
            try:
                subprocess.check_call(argv, env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Magic Leap exited with return value %d" % e.returncode)
                return e.returncode
        elif android:
            android_target = self.config["android"]["target"]
            if "aarch64" in android_target:
                build_type = "Arm64"
            elif "armv7" in android_target:
                build_type = "Armv7"
            elif "i686" in android_target:
                build_type = "x86"
            else:
                build_type = "Arm"

            if dev:
                build_mode = "Debug"
            else:
                build_mode = "Release"

            flavor_name = "Main"
            if flavor is not None:
                flavor_name = flavor.title()

            vr = flavor == "googlevr" or flavor == "oculusvr"

            dir_to_resources = path.join(self.get_top_dir(), 'target', 'android', 'resources')
            if path.exists(dir_to_resources):
                delete(dir_to_resources)

            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            change_prefs(dir_to_resources, "android", vr=vr)

            variant = ":assemble" + flavor_name + build_type + build_mode
            apk_task_name = ":servoapp" + variant
            aar_task_name = ":servoview" + variant
            maven_task_name = ":servoview:uploadArchive"
            argv = ["./gradlew", "--no-daemon", apk_task_name, aar_task_name]
            if maven:
                argv.append(maven_task_name)
            try:
                with cd(path.join("support", "android", "apk")):
                    subprocess.check_call(argv, env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Android exited with return value %d" % e.returncode)
                return e.returncode
        elif is_macosx():
            print("Creating Servo.app")
            dir_to_dmg = path.join(target_dir, 'dmg')
            dir_to_app = path.join(dir_to_dmg, 'Servo.app')
            dir_to_resources = path.join(dir_to_app, 'Contents', 'Resources')
            if path.exists(dir_to_dmg):
                print("Cleaning up from previous packaging")
                delete(dir_to_dmg)

            print("Copying files")
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy2(path.join(dir_to_root, 'Info.plist'), path.join(dir_to_app, 'Contents', 'Info.plist'))

            content_dir = path.join(dir_to_app, 'Contents', 'MacOS')
            os.makedirs(content_dir)
            shutil.copy2(binary_path, content_dir)

            change_prefs(dir_to_resources, "macosx")

            print("Finding dylibs and relinking")
            copy_dependencies(path.join(content_dir, 'servo'), content_dir)

            print("Adding version to Credits.rtf")
            version_command = [binary_path, '--version']
            p = subprocess.Popen(version_command,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            version, stderr = p.communicate()
            if p.returncode != 0:
                raise Exception("Error occurred when getting Servo version: " + stderr)
            version = "Nightly version: " + version

            import mako.template
            template_path = path.join(dir_to_resources, 'Credits.rtf.mako')
            credits_path = path.join(dir_to_resources, 'Credits.rtf')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(credits_path, "w") as credits_file:
                    credits_file.write(template.render(version=version))
            delete(template_path)

            print("Creating dmg")
            os.symlink('/Applications', path.join(dir_to_dmg, 'Applications'))
            dmg_path = path.join(target_dir, "servo-tech-demo.dmg")

            if path.exists(dmg_path):
                print("Deleting existing dmg")
                os.remove(dmg_path)

            try:
                subprocess.check_call(['hdiutil', 'create',
                                       '-volname', 'Servo',
                                       '-megabytes', '900',
                                       dmg_path,
                                       '-srcfolder', dir_to_dmg])
            except subprocess.CalledProcessError as e:
                print("Packaging MacOS dmg exited with return value %d" % e.returncode)
                return e.returncode
            print("Cleaning up")
            delete(dir_to_dmg)
            print("Packaged Servo into " + dmg_path)

            print("Creating brew package")
            dir_to_brew = path.join(target_dir, 'brew_tmp')
            dir_to_tar = path.join(target_dir, 'brew')
            if not path.exists(dir_to_tar):
                os.makedirs(dir_to_tar)
            tar_path = path.join(dir_to_tar, "servo.tar.gz")
            if path.exists(dir_to_brew):
                print("Cleaning up from previous packaging")
                delete(dir_to_brew)
            if path.exists(tar_path):
                print("Deleting existing package")
                os.remove(tar_path)
            shutil.copytree(path.join(dir_to_root, 'resources'), path.join(dir_to_brew, 'resources'))
            os.makedirs(path.join(dir_to_brew, 'bin'))
            shutil.copy2(binary_path, path.join(dir_to_brew, 'bin', 'servo'))
            # Note that in the context of Homebrew, libexec is reserved for private use by the formula
            # and therefore is not symlinked into HOMEBREW_PREFIX.
            os.makedirs(path.join(dir_to_brew, 'libexec'))
            copy_dependencies(path.join(dir_to_brew, 'bin', 'servo'), path.join(dir_to_brew, 'libexec'))
            archive_deterministically(dir_to_brew, tar_path, prepend_path='servo/')
            delete(dir_to_brew)
            print("Packaged Servo into " + tar_path)
        elif is_windows():
            dir_to_msi = path.join(target_dir, 'msi')
            if path.exists(dir_to_msi):
                print("Cleaning up from previous packaging")
                delete(dir_to_msi)
            os.makedirs(dir_to_msi)

            print("Copying files")
            dir_to_temp = path.join(dir_to_msi, 'temp')
            dir_to_resources = path.join(dir_to_temp, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy(binary_path, dir_to_temp)
            copy_windows_dependencies(target_dir, dir_to_temp)

            change_prefs(dir_to_resources, "windows")

            # generate Servo.wxs
            import mako.template
            template_path = path.join(dir_to_root, "support", "windows", "Servo.wxs.mako")
            template = mako.template.Template(open(template_path).read())
            wxs_path = path.join(dir_to_msi, "Installer.wxs")
            open(wxs_path, "w").write(template.render(
                exe_path=target_dir,
                dir_to_temp=dir_to_temp,
                resources_path=dir_to_resources))

            # run candle and light
            print("Creating MSI")
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', wxs_path])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            dir_to_installer = path.join(dir_to_msi, "Installer.msi")
            print("Packaged Servo into " + dir_to_installer)

            # Generate bundle with Servo installer.
            print("Creating bundle")
            shutil.copy(path.join(dir_to_root, 'support', 'windows', 'Servo.wxs'), dir_to_msi)
            bundle_wxs_path = path.join(dir_to_msi, 'Servo.wxs')
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', bundle_wxs_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(bundle_wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.exe"))

            print("Creating ZIP")
            zip_path = path.join(dir_to_msi, "Servo.zip")
            archive_deterministically(dir_to_temp, zip_path, prepend_path='servo/')
            print("Packaged Servo into " + zip_path)

            print("Cleaning up")
            delete(dir_to_temp)
            delete(dir_to_installer)
        else:
            dir_to_temp = path.join(target_dir, 'packaging-temp')
            if path.exists(dir_to_temp):
                # TODO(aneeshusa): lock dir_to_temp to prevent simultaneous builds
                print("Cleaning up from previous packaging")
                delete(dir_to_temp)

            print("Copying files")
            dir_to_resources = path.join(dir_to_temp, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy(binary_path, dir_to_temp)

            change_prefs(dir_to_resources, "linux")

            print("Creating tarball")
            tar_path = path.join(target_dir, 'servo-tech-demo.tar.gz')

            archive_deterministically(dir_to_temp, tar_path, prepend_path='servo/')

            print("Cleaning up")
            delete(dir_to_temp)
            print("Packaged Servo into " + tar_path)
Exemple #10
0
    def clean_cargo_cache(self, force=False, show_size=False, keep=None, custom_path=False):
        def get_size(path):
            if os.path.isfile(path):
                return os.path.getsize(path) / (1024 * 1024.0)
            total_size = 0
            for dirpath, dirnames, filenames in os.walk(path):
                for f in filenames:
                    fp = os.path.join(dirpath, f)
                    total_size += os.path.getsize(fp)
            return total_size / (1024 * 1024.0)

        removing_anything = False
        packages = {
            'crates': {},
            'git': {},
        }
        import toml
        if os.environ.get("CARGO_HOME", "") and custom_path:
            cargo_dir = os.environ.get("CARGO_HOME")
        else:
            cargo_dir = path.join(self.context.topdir, ".cargo")
        if not os.path.isdir(cargo_dir):
            return
        cargo_file = open(path.join(self.context.topdir, "Cargo.lock"))
        content = toml.load(cargo_file)

        for package in content.get("package", []):
            source = package.get("source", "")
            version = package["version"]
            if source == u"registry+https://github.com/rust-lang/crates.io-index":
                crate_name = "{}-{}".format(package["name"], version)
                if not packages["crates"].get(crate_name, False):
                    packages["crates"][package["name"]] = {
                        "current": [],
                        "exist": [],
                    }
                packages["crates"][package["name"]]["current"].append(crate_name)
            elif source.startswith("git+"):
                name = source.split("#")[0].split("/")[-1].replace(".git", "")
                branch = ""
                crate_name = "{}-{}".format(package["name"], source.split("#")[1])
                crate_branch = name.split("?")
                if len(crate_branch) > 1:
                    branch = crate_branch[1].replace("branch=", "")
                    name = crate_branch[0]

                if not packages["git"].get(name, False):
                    packages["git"][name] = {
                        "current": [],
                        "exist": [],
                    }
                packages["git"][name]["current"].append(source.split("#")[1][:7])
                if branch:
                    packages["git"][name]["current"].append(branch)

        crates_dir = path.join(cargo_dir, "registry")
        crates_cache_dir = ""
        crates_src_dir = ""
        if os.path.isdir(path.join(crates_dir, "cache")):
            for p in os.listdir(path.join(crates_dir, "cache")):
                crates_cache_dir = path.join(crates_dir, "cache", p)
                crates_src_dir = path.join(crates_dir, "src", p)

        git_dir = path.join(cargo_dir, "git")
        git_db_dir = path.join(git_dir, "db")
        git_checkout_dir = path.join(git_dir, "checkouts")
        git_db_list = filter(lambda f: not f.startswith('.'), os.listdir(git_db_dir))
        git_checkout_list = os.listdir(git_checkout_dir)

        for d in list(set(git_db_list + git_checkout_list)):
            crate_name = d.replace("-{}".format(d.split("-")[-1]), "")
            if not packages["git"].get(crate_name, False):
                packages["git"][crate_name] = {
                    "current": [],
                    "exist": [],
                }
            if os.path.isdir(path.join(git_checkout_dir, d)):
                with cd(path.join(git_checkout_dir, d)):
                    git_crate_hash = glob.glob('*')
                if not git_crate_hash or not os.path.isdir(path.join(git_db_dir, d)):
                    packages["git"][crate_name]["exist"].append(("del", d, ""))
                    continue
                for d2 in git_crate_hash:
                    dep_path = path.join(git_checkout_dir, d, d2)
                    if os.path.isdir(dep_path):
                        packages["git"][crate_name]["exist"].append((path.getmtime(dep_path), d, d2))
            elif os.path.isdir(path.join(git_db_dir, d)):
                packages["git"][crate_name]["exist"].append(("del", d, ""))

        for d in os.listdir(crates_src_dir):
            crate_name = re.sub(r"\-\d+(\.\d+){1,3}.+", "", d)
            if not packages["crates"].get(crate_name, False):
                packages["crates"][crate_name] = {
                    "current": [],
                    "exist": [],
                }
            packages["crates"][crate_name]["exist"].append(d)

        total_size = 0
        for packages_type in ["git", "crates"]:
            sorted_packages = sorted(packages[packages_type])
            for crate_name in sorted_packages:
                crate_count = 0
                existed_crates = packages[packages_type][crate_name]["exist"]
                for exist in sorted(existed_crates, reverse=True):
                    current_crate = packages[packages_type][crate_name]["current"]
                    size = 0
                    exist_name = path.join(exist[1], exist[2]) if packages_type == "git" else exist
                    exist_item = exist[2] if packages_type == "git" else exist
                    if exist_item not in current_crate:
                        crate_count += 1
                        if int(crate_count) >= int(keep) or not current_crate or \
                           exist[0] == "del" or exist[2] == "master":
                            removing_anything = True
                            crate_paths = []
                            if packages_type == "git":
                                exist_checkout_path = path.join(git_checkout_dir, exist[1])
                                exist_db_path = path.join(git_db_dir, exist[1])
                                exist_path = path.join(git_checkout_dir, exist_name)

                                if exist[0] == "del":
                                    if os.path.isdir(exist_checkout_path):
                                        crate_paths.append(exist_checkout_path)
                                    if os.path.isdir(exist_db_path):
                                        crate_paths.append(exist_db_path)
                                    crate_count += -1
                                else:
                                    crate_paths.append(exist_path)

                                    exist_checkout_list = glob.glob(path.join(exist_checkout_path, '*'))
                                    if len(exist_checkout_list) <= 1:
                                        crate_paths.append(exist_checkout_path)
                                        if os.path.isdir(exist_db_path):
                                            crate_paths.append(exist_db_path)
                            else:
                                crate_paths.append(path.join(crates_cache_dir, "{}.crate".format(exist)))
                                crate_paths.append(path.join(crates_src_dir, exist))

                            size = sum(get_size(p) for p in crate_paths) if show_size else 0
                            total_size += size
                            print_msg = (exist_name, " ({}MB)".format(round(size, 2)) if show_size else "", cargo_dir)
                            if force:
                                print("Removing `{}`{} package from {}".format(*print_msg))
                                for crate_path in crate_paths:
                                    if os.path.exists(crate_path):
                                        delete(crate_path)
                            else:
                                print("Would remove `{}`{} package from {}".format(*print_msg))

        if removing_anything and show_size:
            print("\nTotal size of {} MB".format(round(total_size, 2)))

        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("\nNothing done. "
                  "Run `./mach clean-cargo-cache -f` to actually remove.")
    def clean_cargo_cache(self, force=False, show_size=False, keep=None):
        def get_size(path):
            if os.path.isfile(path):
                return os.path.getsize(path) / (1024 * 1024.0)
            total_size = 0
            for dirpath, dirnames, filenames in os.walk(path):
                for f in filenames:
                    fp = os.path.join(dirpath, f)
                    total_size += os.path.getsize(fp)
            return total_size / (1024 * 1024.0)

        removing_anything = False
        packages = {
            'crates': {},
            'git': {},
        }
        import toml
        if os.environ.get("CARGO_HOME", ""):
            cargo_dir = os.environ.get("CARGO_HOME")
        else:
            home_dir = os.path.expanduser("~")
            cargo_dir = path.join(home_dir, ".cargo")
        if not os.path.isdir(cargo_dir):
            return
        cargo_file = open(path.join(self.context.topdir, "Cargo.lock"))
        content = toml.load(cargo_file)

        for package in content.get("package", []):
            source = package.get("source", "")
            version = package["version"]
            if source == u"registry+https://github.com/rust-lang/crates.io-index":
                crate_name = "{}-{}".format(package["name"], version)
                if not packages["crates"].get(crate_name, False):
                    packages["crates"][package["name"]] = {
                        "current": [],
                        "exist": [],
                    }
                packages["crates"][package["name"]]["current"].append(
                    crate_name)
            elif source.startswith("git+"):
                name = source.split("#")[0].split("/")[-1].replace(".git", "")
                branch = ""
                crate_name = "{}-{}".format(package["name"],
                                            source.split("#")[1])
                crate_branch = name.split("?")
                if len(crate_branch) > 1:
                    branch = crate_branch[1].replace("branch=", "")
                    name = crate_branch[0]

                if not packages["git"].get(name, False):
                    packages["git"][name] = {
                        "current": [],
                        "exist": [],
                    }
                packages["git"][name]["current"].append(
                    source.split("#")[1][:7])
                if branch:
                    packages["git"][name]["current"].append(branch)

        crates_dir = path.join(cargo_dir, "registry")
        crates_cache_dir = ""
        crates_src_dir = ""
        if os.path.isdir(path.join(crates_dir, "cache")):
            for p in os.listdir(path.join(crates_dir, "cache")):
                crates_cache_dir = path.join(crates_dir, "cache", p)
                crates_src_dir = path.join(crates_dir, "src", p)

        git_dir = path.join(cargo_dir, "git")
        git_db_dir = path.join(git_dir, "db")
        git_checkout_dir = path.join(git_dir, "checkouts")
        if os.path.isdir(git_db_dir):
            git_db_list = filter(lambda f: not f.startswith('.'),
                                 os.listdir(git_db_dir))
        else:
            git_db_list = []
        if os.path.isdir(git_checkout_dir):
            git_checkout_list = os.listdir(git_checkout_dir)
        else:
            git_checkout_list = []

        for d in list(set(git_db_list + git_checkout_list)):
            crate_name = d.replace("-{}".format(d.split("-")[-1]), "")
            if not packages["git"].get(crate_name, False):
                packages["git"][crate_name] = {
                    "current": [],
                    "exist": [],
                }
            if os.path.isdir(path.join(git_checkout_dir, d)):
                with cd(path.join(git_checkout_dir, d)):
                    git_crate_hash = glob.glob('*')
                if not git_crate_hash or not os.path.isdir(
                        path.join(git_db_dir, d)):
                    packages["git"][crate_name]["exist"].append(("del", d, ""))
                    continue
                for d2 in git_crate_hash:
                    dep_path = path.join(git_checkout_dir, d, d2)
                    if os.path.isdir(dep_path):
                        packages["git"][crate_name]["exist"].append(
                            (path.getmtime(dep_path), d, d2))
            elif os.path.isdir(path.join(git_db_dir, d)):
                packages["git"][crate_name]["exist"].append(("del", d, ""))

        for d in os.listdir(crates_src_dir):
            crate_name = re.sub(r"\-\d+(\.\d+){1,3}.+", "", d)
            if not packages["crates"].get(crate_name, False):
                packages["crates"][crate_name] = {
                    "current": [],
                    "exist": [],
                }
            packages["crates"][crate_name]["exist"].append(d)

        total_size = 0
        for packages_type in ["git", "crates"]:
            sorted_packages = sorted(packages[packages_type])
            for crate_name in sorted_packages:
                crate_count = 0
                existed_crates = packages[packages_type][crate_name]["exist"]
                for exist in sorted(existed_crates, reverse=True):
                    current_crate = packages[packages_type][crate_name][
                        "current"]
                    size = 0
                    exist_name = path.join(
                        exist[1],
                        exist[2]) if packages_type == "git" else exist
                    exist_item = exist[2] if packages_type == "git" else exist
                    if exist_item not in current_crate:
                        crate_count += 1
                        if int(crate_count) >= int(keep) or not current_crate or \
                           exist[0] == "del" or exist[2] == "master":
                            removing_anything = True
                            crate_paths = []
                            if packages_type == "git":
                                exist_checkout_path = path.join(
                                    git_checkout_dir, exist[1])
                                exist_db_path = path.join(git_db_dir, exist[1])
                                exist_path = path.join(git_checkout_dir,
                                                       exist_name)

                                if exist[0] == "del":
                                    if os.path.isdir(exist_checkout_path):
                                        crate_paths.append(exist_checkout_path)
                                    if os.path.isdir(exist_db_path):
                                        crate_paths.append(exist_db_path)
                                    crate_count += -1
                                else:
                                    crate_paths.append(exist_path)

                                    exist_checkout_list = glob.glob(
                                        path.join(exist_checkout_path, '*'))
                                    if len(exist_checkout_list) <= 1:
                                        crate_paths.append(exist_checkout_path)
                                        if os.path.isdir(exist_db_path):
                                            crate_paths.append(exist_db_path)
                            else:
                                crate_paths.append(
                                    path.join(crates_cache_dir,
                                              "{}.crate".format(exist)))
                                crate_paths.append(
                                    path.join(crates_src_dir, exist))

                            size = sum(
                                get_size(p)
                                for p in crate_paths) if show_size else 0
                            total_size += size
                            print_msg = (exist_name, " ({}MB)".format(
                                round(size, 2)) if show_size else "",
                                         cargo_dir)
                            if force:
                                print("Removing `{}`{} package from {}".format(
                                    *print_msg))
                                for crate_path in crate_paths:
                                    if os.path.exists(crate_path):
                                        try:
                                            delete(crate_path)
                                        except:
                                            print(traceback.format_exc())
                                            print("Delete %s failed!" %
                                                  crate_path)
                            else:
                                print("Would remove `{}`{} package from {}".
                                      format(*print_msg))

        if removing_anything and show_size:
            print("\nTotal size of {} MB".format(round(total_size, 2)))

        if not removing_anything:
            print("Nothing to remove.")
        elif not force:
            print("\nNothing done. "
                  "Run `./mach clean-cargo-cache -f` to actually remove.")
Exemple #12
0
    def package(self, release=False, dev=False, android=None, debug=False, debugger=None, target=None):
        env = self.build_env()
        if android is None:
            android = self.config["build"]["android"]
        if target and android:
            print("Please specify either --target or --android.")
            sys.exit(1)
        if not android:
            android = self.handle_android_target(target)
        binary_path = self.get_binary_path(release, dev, android=android)
        dir_to_root = self.get_top_dir()
        target_dir = path.dirname(binary_path)
        if android:
            android_target = self.config["android"]["target"]
            if "aarch64" in android_target:
                build_type = "Arm64"
            elif "armv7" in android_target:
                build_type = "Armv7"
            else:
                build_type = "Arm"

            if dev:
                build_mode = "Debug"
            else:
                build_mode = "Release"

            task_name = "assemble" + build_type + build_mode
            try:
                with cd(path.join("support", "android", "apk")):
                    subprocess.check_call(["./gradlew", "--no-daemon", task_name], env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Android exited with return value %d" % e.returncode)
                return e.returncode
        elif is_macosx():
            print("Creating Servo.app")
            dir_to_dmg = path.join(target_dir, 'dmg')
            dir_to_app = path.join(dir_to_dmg, 'Servo.app')
            dir_to_resources = path.join(dir_to_app, 'Contents', 'Resources')
            if path.exists(dir_to_dmg):
                print("Cleaning up from previous packaging")
                delete(dir_to_dmg)
            browserhtml_path = get_browserhtml_path(binary_path)

            print("Copying files")
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copytree(browserhtml_path, path.join(dir_to_resources, 'browserhtml'))
            shutil.copy2(path.join(dir_to_root, 'Info.plist'), path.join(dir_to_app, 'Contents', 'Info.plist'))

            content_dir = path.join(dir_to_app, 'Contents', 'MacOS')
            os.makedirs(content_dir)
            shutil.copy2(binary_path, content_dir)

            change_prefs(dir_to_resources, "macosx")

            print("Finding dylibs and relinking")
            copy_dependencies(path.join(content_dir, 'servo'), content_dir)

            print("Adding version to Credits.rtf")
            version_command = [binary_path, '--version']
            p = subprocess.Popen(version_command,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            version, stderr = p.communicate()
            if p.returncode != 0:
                raise Exception("Error occurred when getting Servo version: " + stderr)
            version = "Nightly version: " + version

            import mako.template
            template_path = path.join(dir_to_resources, 'Credits.rtf.mako')
            credits_path = path.join(dir_to_resources, 'Credits.rtf')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(credits_path, "w") as credits_file:
                    credits_file.write(template.render(version=version))
            delete(template_path)

            print("Writing run-servo")
            bhtml_path = path.join('${0%/*}', '..', 'Resources', 'browserhtml', 'index.html')
            runservo = os.open(
                path.join(content_dir, 'run-servo'),
                os.O_WRONLY | os.O_CREAT,
                int("0755", 8)
            )
            os.write(runservo, '#!/bin/bash\nexec ${0%/*}/servo ' + bhtml_path)
            os.close(runservo)

            print("Creating dmg")
            os.symlink('/Applications', path.join(dir_to_dmg, 'Applications'))
            dmg_path = path.join(target_dir, "servo-tech-demo.dmg")

            if path.exists(dmg_path):
                print("Deleting existing dmg")
                os.remove(dmg_path)

            try:
                subprocess.check_call(['hdiutil', 'create',
                                       '-volname', 'Servo',
                                       '-megabytes', '900',
                                       dmg_path,
                                       '-srcfolder', dir_to_dmg])
            except subprocess.CalledProcessError as e:
                print("Packaging MacOS dmg exited with return value %d" % e.returncode)
                return e.returncode
            print("Cleaning up")
            delete(dir_to_dmg)
            print("Packaged Servo into " + dmg_path)

            print("Creating brew package")
            dir_to_brew = path.join(target_dir, 'brew_tmp')
            dir_to_tar = path.join(target_dir, 'brew')
            if not path.exists(dir_to_tar):
                os.makedirs(dir_to_tar)
            tar_path = path.join(dir_to_tar, "servo.tar.gz")
            if path.exists(dir_to_brew):
                print("Cleaning up from previous packaging")
                delete(dir_to_brew)
            if path.exists(tar_path):
                print("Deleting existing package")
                os.remove(tar_path)
            shutil.copytree(path.join(dir_to_root, 'resources'), path.join(dir_to_brew, 'resources'))
            os.makedirs(path.join(dir_to_brew, 'bin'))
            shutil.copy2(binary_path, path.join(dir_to_brew, 'bin', 'servo'))
            # Note that in the context of Homebrew, libexec is reserved for private use by the formula
            # and therefore is not symlinked into HOMEBREW_PREFIX.
            os.makedirs(path.join(dir_to_brew, 'libexec'))
            copy_dependencies(path.join(dir_to_brew, 'bin', 'servo'), path.join(dir_to_brew, 'libexec'))
            archive_deterministically(dir_to_brew, tar_path, prepend_path='servo/')
            delete(dir_to_brew)
            print("Packaged Servo into " + tar_path)
        elif is_windows():
            dir_to_msi = path.join(target_dir, 'msi')
            if path.exists(dir_to_msi):
                print("Cleaning up from previous packaging")
                delete(dir_to_msi)
            os.makedirs(dir_to_msi)
            browserhtml_path = get_browserhtml_path(binary_path)

            print("Copying files")
            dir_to_temp = path.join(dir_to_msi, 'temp')
            dir_to_temp_servo = path.join(dir_to_temp, 'servo')
            dir_to_resources = path.join(dir_to_temp_servo, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copytree(browserhtml_path, path.join(dir_to_temp_servo, 'browserhtml'))
            shutil.copy(binary_path, dir_to_temp_servo)
            shutil.copy("{}.manifest".format(binary_path), dir_to_temp_servo)
            copy_windows_dependencies(target_dir, dir_to_temp_servo)

            change_prefs(dir_to_resources, "windows")

            # generate Servo.wxs
            import mako.template
            template_path = path.join(dir_to_root, "support", "windows", "Servo.wxs.mako")
            template = mako.template.Template(open(template_path).read())
            wxs_path = path.join(dir_to_msi, "Servo.wxs")
            open(wxs_path, "w").write(template.render(
                exe_path=target_dir,
                dir_to_temp=dir_to_temp_servo,
                resources_path=dir_to_resources))

            # run candle and light
            print("Creating MSI")
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', wxs_path])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.msi"))

            print("Creating ZIP")
            shutil.make_archive(path.join(dir_to_msi, "Servo"), "zip", dir_to_temp)
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.zip"))

            print("Cleaning up")
            delete(dir_to_temp)
        else:
            dir_to_temp = path.join(target_dir, 'packaging-temp')
            browserhtml_path = get_browserhtml_path(binary_path)
            if path.exists(dir_to_temp):
                # TODO(aneeshusa): lock dir_to_temp to prevent simultaneous builds
                print("Cleaning up from previous packaging")
                delete(dir_to_temp)

            print("Copying files")
            dir_to_resources = path.join(dir_to_temp, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copytree(browserhtml_path, path.join(dir_to_temp, 'browserhtml'))
            shutil.copy(binary_path, dir_to_temp)

            change_prefs(dir_to_resources, "linux")

            print("Creating tarball")
            tar_path = path.join(target_dir, 'servo-tech-demo.tar.gz')

            archive_deterministically(dir_to_temp, tar_path, prepend_path='servo/')

            print("Cleaning up")
            delete(dir_to_temp)
            print("Packaged Servo into " + tar_path)
Exemple #13
0
    def package(self,
                release=False,
                dev=False,
                android=None,
                debug=False,
                debugger=None,
                target=None,
                flavor=None):
        if android is None:
            android = self.config["build"]["android"]
        if target and android:
            print("Please specify either --target or --android.")
            sys.exit(1)
        if not android:
            android = self.handle_android_target(target)
        else:
            target = self.config["android"]["target"]
        env = self.build_env(target=target)
        binary_path = self.get_binary_path(release, dev, android=android)
        dir_to_root = self.get_top_dir()
        target_dir = path.dirname(binary_path)
        if android:
            android_target = self.config["android"]["target"]
            if "aarch64" in android_target:
                build_type = "Arm64"
            elif "armv7" in android_target:
                build_type = "Armv7"
            elif "i686" in android_target:
                build_type = "x86"
            else:
                build_type = "Arm"

            if dev:
                build_mode = "Debug"
            else:
                build_mode = "Release"

            flavor_name = "Main"
            if flavor is not None:
                flavor_name = flavor.title()

            variant = ":assemble" + flavor_name + build_type + build_mode
            apk_task_name = ":servoapp" + variant
            aar_task_name = ":servoview" + variant
            try:
                with cd(path.join("support", "android", "apk")):
                    subprocess.check_call([
                        "./gradlew", "--no-daemon", apk_task_name,
                        aar_task_name
                    ],
                                          env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Android exited with return value %d" %
                      e.returncode)
                return e.returncode
        elif is_macosx():
            print("Creating Servo.app")
            dir_to_dmg = path.join(target_dir, 'dmg')
            dir_to_app = path.join(dir_to_dmg, 'Servo.app')
            dir_to_resources = path.join(dir_to_app, 'Contents', 'Resources')
            if path.exists(dir_to_dmg):
                print("Cleaning up from previous packaging")
                delete(dir_to_dmg)

            print("Copying files")
            shutil.copytree(path.join(dir_to_root, 'resources'),
                            dir_to_resources)
            shutil.copy2(path.join(dir_to_root, 'Info.plist'),
                         path.join(dir_to_app, 'Contents', 'Info.plist'))

            content_dir = path.join(dir_to_app, 'Contents', 'MacOS')
            os.makedirs(content_dir)
            shutil.copy2(binary_path, content_dir)

            change_prefs(dir_to_resources, "macosx")

            print("Finding dylibs and relinking")
            copy_dependencies(path.join(content_dir, 'servo'), content_dir)

            print("Adding version to Credits.rtf")
            version_command = [binary_path, '--version']
            p = subprocess.Popen(version_command,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            version, stderr = p.communicate()
            if p.returncode != 0:
                raise Exception("Error occurred when getting Servo version: " +
                                stderr)
            version = "Nightly version: " + version

            import mako.template
            template_path = path.join(dir_to_resources, 'Credits.rtf.mako')
            credits_path = path.join(dir_to_resources, 'Credits.rtf')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(credits_path, "w") as credits_file:
                    credits_file.write(template.render(version=version))
            delete(template_path)

            print("Creating dmg")
            os.symlink('/Applications', path.join(dir_to_dmg, 'Applications'))
            dmg_path = path.join(target_dir, "servo-tech-demo.dmg")

            if path.exists(dmg_path):
                print("Deleting existing dmg")
                os.remove(dmg_path)

            try:
                subprocess.check_call([
                    'hdiutil', 'create', '-volname', 'Servo', '-megabytes',
                    '900', dmg_path, '-srcfolder', dir_to_dmg
                ])
            except subprocess.CalledProcessError as e:
                print("Packaging MacOS dmg exited with return value %d" %
                      e.returncode)
                return e.returncode
            print("Cleaning up")
            delete(dir_to_dmg)
            print("Packaged Servo into " + dmg_path)

            print("Creating brew package")
            dir_to_brew = path.join(target_dir, 'brew_tmp')
            dir_to_tar = path.join(target_dir, 'brew')
            if not path.exists(dir_to_tar):
                os.makedirs(dir_to_tar)
            tar_path = path.join(dir_to_tar, "servo.tar.gz")
            if path.exists(dir_to_brew):
                print("Cleaning up from previous packaging")
                delete(dir_to_brew)
            if path.exists(tar_path):
                print("Deleting existing package")
                os.remove(tar_path)
            shutil.copytree(path.join(dir_to_root, 'resources'),
                            path.join(dir_to_brew, 'resources'))
            os.makedirs(path.join(dir_to_brew, 'bin'))
            shutil.copy2(binary_path, path.join(dir_to_brew, 'bin', 'servo'))
            # Note that in the context of Homebrew, libexec is reserved for private use by the formula
            # and therefore is not symlinked into HOMEBREW_PREFIX.
            os.makedirs(path.join(dir_to_brew, 'libexec'))
            copy_dependencies(path.join(dir_to_brew, 'bin', 'servo'),
                              path.join(dir_to_brew, 'libexec'))
            archive_deterministically(dir_to_brew,
                                      tar_path,
                                      prepend_path='servo/')
            delete(dir_to_brew)
            print("Packaged Servo into " + tar_path)
        elif is_windows():
            dir_to_msi = path.join(target_dir, 'msi')
            if path.exists(dir_to_msi):
                print("Cleaning up from previous packaging")
                delete(dir_to_msi)
            os.makedirs(dir_to_msi)

            print("Copying files")
            dir_to_temp = path.join(dir_to_msi, 'temp')
            dir_to_temp_servo = path.join(dir_to_temp, 'servo')
            dir_to_resources = path.join(dir_to_temp_servo, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'),
                            dir_to_resources)
            shutil.copy(binary_path, dir_to_temp_servo)
            copy_windows_dependencies(target_dir, dir_to_temp_servo)

            change_prefs(dir_to_resources, "windows")

            # generate Servo.wxs
            import mako.template
            template_path = path.join(dir_to_root, "support", "windows",
                                      "Servo.wxs.mako")
            template = mako.template.Template(open(template_path).read())
            wxs_path = path.join(dir_to_msi, "Installer.wxs")
            open(wxs_path, "w").write(
                template.render(exe_path=target_dir,
                                dir_to_temp=dir_to_temp_servo,
                                resources_path=dir_to_resources))

            # run candle and light
            print("Creating MSI")
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', wxs_path])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged Servo into " +
                  path.join(dir_to_msi, "Installer.msi"))

            # Download GStreamer installer. Only once.
            dir_to_gst_deps = path.join(dir_to_msi, 'Gstreamer.msi')
            gstreamer_msi_path = path.join(target_dir, 'Gstreamer.msi')
            if not os.path.exists(gstreamer_msi_path):
                print('Fetching GStreamer installer. This may take a while...')
                gstreamer_url = 'https://gstreamer.freedesktop.org/data/pkg/windows/1.14.2/gstreamer-1.0-x86-1.14.2.msi'
                urllib.urlretrieve(gstreamer_url, gstreamer_msi_path)
            shutil.copy(gstreamer_msi_path, dir_to_gst_deps)

            # Generate bundle with GStreamer and Servo installers.
            print("Creating bundle")
            shutil.copy(
                path.join(dir_to_root, 'support', 'windows', 'Servo.wxs'),
                dir_to_msi)
            bundle_wxs_path = path.join(dir_to_msi, 'Servo.wxs')
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(
                        ['candle', bundle_wxs_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(
                    path.splitext(bundle_wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(
                        ['light', wxsobj_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.msi"))

            print("Creating ZIP")
            shutil.make_archive(path.join(dir_to_msi, "Servo"), "zip",
                                dir_to_temp)
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.zip"))

            print("Cleaning up")
            delete(dir_to_temp)
        else:
            dir_to_temp = path.join(target_dir, 'packaging-temp')
            if path.exists(dir_to_temp):
                # TODO(aneeshusa): lock dir_to_temp to prevent simultaneous builds
                print("Cleaning up from previous packaging")
                delete(dir_to_temp)

            print("Copying files")
            dir_to_resources = path.join(dir_to_temp, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'),
                            dir_to_resources)
            shutil.copy(binary_path, dir_to_temp)

            change_prefs(dir_to_resources, "linux")

            print("Creating tarball")
            tar_path = path.join(target_dir, 'servo-tech-demo.tar.gz')

            archive_deterministically(dir_to_temp,
                                      tar_path,
                                      prepend_path='servo/')

            print("Cleaning up")
            delete(dir_to_temp)
            print("Packaged Servo into " + tar_path)
Exemple #14
0
    def package(self, release=False, dev=False, android=None, magicleap=None, debug=False,
                debugger=None, target=None, flavor=None, maven=False):
        if android is None:
            android = self.config["build"]["android"]
        if target and android:
            print("Please specify either --target or --android.")
            sys.exit(1)
        if not android:
            android = self.handle_android_target(target)
        else:
            target = self.config["android"]["target"]
        env = self.build_env(target=target)
        binary_path = self.get_binary_path(release, dev, android=android, magicleap=magicleap)
        dir_to_root = self.get_top_dir()
        target_dir = path.dirname(binary_path)
        if magicleap:
            if platform.system() not in ["Darwin"]:
                raise Exception("Magic Leap builds are only supported on macOS.")
            if not env.get("MAGICLEAP_SDK"):
                raise Exception("Magic Leap builds need the MAGICLEAP_SDK environment variable")
            if not env.get("MLCERT"):
                raise Exception("Magic Leap builds need the MLCERT environment variable")
            mabu = path.join(env.get("MAGICLEAP_SDK"), "mabu")
            package = "./support/magicleap/Servo2D/Servo2D.package"
            if dev:
                build_type = "lumin_debug"
            else:
                build_type = "lumin_release"
            argv = [
                mabu,
                "-o", target_dir,
                "-t", build_type,
                # Servo SEGVs if we don't set the debuggable flag in the mpk's taildata
                # https://github.com/servo/servo/issues/22188
                "--add-tail-data-args=--debuggable",
                package
            ]
            try:
                subprocess.check_call(argv, env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Magic Leap exited with return value %d" % e.returncode)
                return e.returncode
        elif android:
            android_target = self.config["android"]["target"]
            if "aarch64" in android_target:
                build_type = "Arm64"
            elif "armv7" in android_target:
                build_type = "Armv7"
            elif "i686" in android_target:
                build_type = "x86"
            else:
                build_type = "Arm"

            if dev:
                build_mode = "Debug"
            else:
                build_mode = "Release"

            flavor_name = "Main"
            if flavor is not None:
                flavor_name = flavor.title()

            vr = flavor == "googlevr" or flavor == "oculusvr"

            dir_to_resources = path.join(self.get_top_dir(), 'target', 'android', 'resources')
            if path.exists(dir_to_resources):
                delete(dir_to_resources)

            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            change_prefs(dir_to_resources, "android", vr=vr)

            variant = ":assemble" + flavor_name + build_type + build_mode
            apk_task_name = ":servoapp" + variant
            aar_task_name = ":servoview" + variant
            maven_task_name = ":servoview:uploadArchive"
            argv = ["./gradlew", "--no-daemon", apk_task_name, aar_task_name]
            if maven:
                argv.append(maven_task_name)
            try:
                with cd(path.join("support", "android", "apk")):
                    subprocess.check_call(argv, env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Android exited with return value %d" % e.returncode)
                return e.returncode
        elif is_macosx():
            print("Creating Servo.app")
            dir_to_dmg = path.join(target_dir, 'dmg')
            dir_to_app = path.join(dir_to_dmg, 'Servo.app')
            dir_to_resources = path.join(dir_to_app, 'Contents', 'Resources')
            if path.exists(dir_to_dmg):
                print("Cleaning up from previous packaging")
                delete(dir_to_dmg)

            print("Copying files")
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy2(path.join(dir_to_root, 'Info.plist'), path.join(dir_to_app, 'Contents', 'Info.plist'))

            content_dir = path.join(dir_to_app, 'Contents', 'MacOS')
            os.makedirs(content_dir)
            shutil.copy2(binary_path, content_dir)

            change_prefs(dir_to_resources, "macosx")

            print("Finding dylibs and relinking")
            copy_dependencies(path.join(content_dir, 'servo'), content_dir)

            print("Adding version to Credits.rtf")
            version_command = [binary_path, '--version']
            p = subprocess.Popen(version_command,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            version, stderr = p.communicate()
            if p.returncode != 0:
                raise Exception("Error occurred when getting Servo version: " + stderr)
            version = "Nightly version: " + version

            import mako.template
            template_path = path.join(dir_to_resources, 'Credits.rtf.mako')
            credits_path = path.join(dir_to_resources, 'Credits.rtf')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(credits_path, "w") as credits_file:
                    credits_file.write(template.render(version=version))
            delete(template_path)

            print("Creating dmg")
            os.symlink('/Applications', path.join(dir_to_dmg, 'Applications'))
            dmg_path = path.join(target_dir, "servo-tech-demo.dmg")

            if path.exists(dmg_path):
                print("Deleting existing dmg")
                os.remove(dmg_path)

            try:
                subprocess.check_call(['hdiutil', 'create',
                                       '-volname', 'Servo',
                                       '-megabytes', '900',
                                       dmg_path,
                                       '-srcfolder', dir_to_dmg])
            except subprocess.CalledProcessError as e:
                print("Packaging MacOS dmg exited with return value %d" % e.returncode)
                return e.returncode
            print("Cleaning up")
            delete(dir_to_dmg)
            print("Packaged Servo into " + dmg_path)

            print("Creating brew package")
            dir_to_brew = path.join(target_dir, 'brew_tmp')
            dir_to_tar = path.join(target_dir, 'brew')
            if not path.exists(dir_to_tar):
                os.makedirs(dir_to_tar)
            tar_path = path.join(dir_to_tar, "servo.tar.gz")
            if path.exists(dir_to_brew):
                print("Cleaning up from previous packaging")
                delete(dir_to_brew)
            if path.exists(tar_path):
                print("Deleting existing package")
                os.remove(tar_path)
            shutil.copytree(path.join(dir_to_root, 'resources'), path.join(dir_to_brew, 'resources'))
            os.makedirs(path.join(dir_to_brew, 'bin'))
            shutil.copy2(binary_path, path.join(dir_to_brew, 'bin', 'servo'))
            # Note that in the context of Homebrew, libexec is reserved for private use by the formula
            # and therefore is not symlinked into HOMEBREW_PREFIX.
            os.makedirs(path.join(dir_to_brew, 'libexec'))
            copy_dependencies(path.join(dir_to_brew, 'bin', 'servo'), path.join(dir_to_brew, 'libexec'))
            archive_deterministically(dir_to_brew, tar_path, prepend_path='servo/')
            delete(dir_to_brew)
            print("Packaged Servo into " + tar_path)
        elif is_windows():
            dir_to_msi = path.join(target_dir, 'msi')
            if path.exists(dir_to_msi):
                print("Cleaning up from previous packaging")
                delete(dir_to_msi)
            os.makedirs(dir_to_msi)

            print("Copying files")
            dir_to_temp = path.join(dir_to_msi, 'temp')
            dir_to_temp_servo = path.join(dir_to_temp, 'servo')
            dir_to_resources = path.join(dir_to_temp_servo, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy(binary_path, dir_to_temp_servo)
            copy_windows_dependencies(target_dir, dir_to_temp_servo)

            change_prefs(dir_to_resources, "windows")

            # generate Servo.wxs
            import mako.template
            template_path = path.join(dir_to_root, "support", "windows", "Servo.wxs.mako")
            template = mako.template.Template(open(template_path).read())
            wxs_path = path.join(dir_to_msi, "Installer.wxs")
            open(wxs_path, "w").write(template.render(
                exe_path=target_dir,
                dir_to_temp=dir_to_temp_servo,
                resources_path=dir_to_resources))

            # run candle and light
            print("Creating MSI")
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', wxs_path])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            dir_to_installer = path.join(dir_to_msi, "Installer.msi")
            print("Packaged Servo into " + dir_to_installer)

            # Download GStreamer installer. Only once.
            gstreamer_msi_path = path.join(dir_to_msi, 'Gstreamer.msi')
            if not os.path.exists(gstreamer_msi_path):
                print('Fetching GStreamer installer. This may take a while...')
                gstreamer_url = 'https://gstreamer.freedesktop.org/data/pkg/windows/1.14.2/gstreamer-1.0-x86-1.14.2.msi'
                urllib.urlretrieve(gstreamer_url, gstreamer_msi_path)

            # Generate bundle with GStreamer and Servo installers.
            print("Creating bundle")
            shutil.copy(path.join(dir_to_root, 'support', 'windows', 'Servo.wxs'), dir_to_msi)
            bundle_wxs_path = path.join(dir_to_msi, 'Servo.wxs')
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', bundle_wxs_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(bundle_wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path, '-ext', 'WixBalExtension'])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.msi"))

            print("Creating ZIP")
            shutil.make_archive(path.join(dir_to_msi, "Servo"), "zip", dir_to_temp)
            print("Packaged Servo into " + path.join(dir_to_msi, "Servo.zip"))

            print("Cleaning up")
            delete(dir_to_temp)
            delete(dir_to_installer)
        else:
            dir_to_temp = path.join(target_dir, 'packaging-temp')
            if path.exists(dir_to_temp):
                # TODO(aneeshusa): lock dir_to_temp to prevent simultaneous builds
                print("Cleaning up from previous packaging")
                delete(dir_to_temp)

            print("Copying files")
            dir_to_resources = path.join(dir_to_temp, 'resources')
            shutil.copytree(path.join(dir_to_root, 'resources'), dir_to_resources)
            shutil.copy(binary_path, dir_to_temp)

            change_prefs(dir_to_resources, "linux")

            print("Creating tarball")
            tar_path = path.join(target_dir, 'servo-tech-demo.tar.gz')

            archive_deterministically(dir_to_temp, tar_path, prepend_path='servo/')

            print("Cleaning up")
            delete(dir_to_temp)
            print("Packaged Servo into " + tar_path)
    def package(self, release=False, dev=False, android=None, debug=False, debugger=None, target=None):
        env = self.build_env()
        if android is None:
            android = self.config["build"]["android"]
        if target and android:
            print("Please specify either --target or --android.")
            sys.exit(1)
        if not android:
            android = self.handle_android_target(target)
        binary_path = self.get_binary_path(release, dev, android=android)
        dir_to_root = self.get_top_dir()
        target_dir = path.dirname(binary_path)
        if android:
            android_target = self.config["android"]["target"]
            if "aarch64" in android_target:
                build_type = "Arm64"
            elif "armv7" in android_target:
                build_type = "Armv7"
            else:
                build_type = "Arm"

            if dev:
                build_mode = "Debug"
            else:
                build_mode = "Release"

            task_name = "assemble" + build_type + build_mode
            try:
                with cd(path.join("support", "android", "apk")):
                    subprocess.check_call(["./gradlew", "--no-daemon", task_name], env=env)
            except subprocess.CalledProcessError as e:
                print("Packaging Android exited with return value %d" % e.returncode)
                return e.returncode
        elif is_macosx():
            print("Creating ServoShell.app")
            dir_to_dmg = path.join(target_dir, 'dmg')
            dir_to_app = path.join(dir_to_dmg, 'ServoShell.app')
            dir_to_resources = path.join(dir_to_app, 'Contents', 'Resources')
            if path.exists(dir_to_dmg):
                print("Cleaning up from previous packaging")
                delete(dir_to_dmg)

            mmtabbar_path = path.join(self.get_target_dir(), 'MMTabBarView', 'Release', 'MMTabBarView.framework')
            if path.exists(mmtabbar_path):
                dir_to_framework = path.join(dir_to_app, 'Contents', 'Frameworks', 'MMTabBarView.framework')
                shutil.copytree(mmtabbar_path, dir_to_framework)
                nibs_path = path.join(self.get_target_dir(), 'nibs')
                shutil.copytree(nibs_path, dir_to_resources + '/nibs')

            print("Copying files")
            shutil.copytree(path.join(dir_to_root, 'servo_resources'), path.join(dir_to_resources, 'servo_resources'))
            shutil.copytree(path.join(dir_to_root, 'shell_resources'), path.join(dir_to_resources, 'shell_resources'))

            content_dir = path.join(dir_to_app, 'Contents', 'MacOS')
            os.makedirs(content_dir)
            shutil.copy2(binary_path, content_dir)

            print("Finding dylibs and relinking")
            copy_dependencies(path.join(content_dir, 'servoshell'), content_dir)

            print("Adding version to Credits.rtf")
            version_command = [binary_path, '--version']
            p = subprocess.Popen(version_command,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            version, stderr = p.communicate()
            if p.returncode != 0:
                raise Exception("Error occurred when getting ServoShell version: " + stderr)

            import mako.template

            template_path = path.join(dir_to_root, "support", "macos", "Credits.rtf.mako")
            credits_path = path.join(dir_to_resources, 'Credits.rtf')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(credits_path, "w") as credits_file:
                    credits_file.write(template.render(version=version))

            template_path = path.join(dir_to_root, "support", "macos", "Info.plist.mako")
            plist_path = path.join(dir_to_app, 'Contents', 'Info.plist')
            with open(template_path) as template_file:
                template = mako.template.Template(template_file.read())
                with open(plist_path, "w") as plist_file:
                    plist_file.write(template.render(version=version))

            print("Creating dmg")
            os.symlink('/Applications', path.join(dir_to_dmg, 'Applications'))
            dmg_path = path.join(target_dir, "servoshell.dmg")

            if path.exists(dmg_path):
                print("Deleting existing dmg")
                os.remove(dmg_path)

            try:
                subprocess.check_call(['hdiutil', 'create',
                                       '-volname', 'Servo',
                                       '-megabytes', '900',
                                       dmg_path,
                                       '-srcfolder', dir_to_dmg])
            except subprocess.CalledProcessError as e:
                print("Packaging MacOS dmg exited with return value %d" % e.returncode)
                return e.returncode
            print("Cleaning up")
            delete(dir_to_dmg)
            print("Packaged Servo into " + dmg_path)

        elif is_windows():
            dir_to_msi = path.join(target_dir, 'msi')
            if path.exists(dir_to_msi):
                print("Cleaning up from previous packaging")
                delete(dir_to_msi)
            os.makedirs(dir_to_msi)

            print("Copying files")
            dir_to_temp = path.join(dir_to_msi, 'temp')
            dir_to_temp_servo = path.join(dir_to_temp, 'servoshell')
            dir_to_resources = path.join(dir_to_temp_servo, 'resources')
            shutil.copytree(path.join(dir_to_root, 'shell_resources'), path.join(dir_to_resources, 'shell_resources'))
            shutil.copytree(path.join(dir_to_root, 'servo_resources'), path.join(dir_to_resources, 'servo_resources'))
            shutil.copy(binary_path, dir_to_temp_servo)
            shutil.copy("{}.manifest".format(binary_path), dir_to_temp_servo)
            copy_windows_dependencies(target_dir, dir_to_temp_servo)

            # generate Servo.wxs
            import mako.template
            template_path = path.join(dir_to_root, "support", "windows", "ServoShell.wxs.mako")
            template = mako.template.Template(open(template_path).read())
            wxs_path = path.join(dir_to_msi, "ServoShell.wxs")
            open(wxs_path, "w").write(template.render(
                exe_path=target_dir,
                dir_to_temp=dir_to_temp_servo,
                resources_path=dir_to_resources))

            # run candle and light
            print("Creating MSI: " + wxs_path)
            try:
                with cd(dir_to_msi):
                    subprocess.check_call(['candle', wxs_path])
            except subprocess.CalledProcessError as e:
                print("WiX candle exited with return value %d" % e.returncode)
                return e.returncode
            try:
                wxsobj_path = "{}.wixobj".format(path.splitext(wxs_path)[0])
                with cd(dir_to_msi):
                    subprocess.check_call(['light', wxsobj_path])
            except subprocess.CalledProcessError as e:
                print("WiX light exited with return value %d" % e.returncode)
                return e.returncode
            print("Packaged ServoShell into " + path.join(dir_to_msi, "ServoShell.msi"))

            print("Creating ZIP")
            shutil.make_archive(path.join(dir_to_msi, "ServoShell"), "zip", dir_to_temp)
            print("Packaged ServoShell into " + path.join(dir_to_msi, "ServoShell.zip"))

            print("Cleaning up")
            delete(dir_to_temp)
        else:
            dir_to_temp = path.join(target_dir, 'packaging-temp')
            if path.exists(dir_to_temp):
                # TODO(aneeshusa): lock dir_to_temp to prevent simultaneous builds
                print("Cleaning up from previous packaging")
                delete(dir_to_temp)

            print("Copying files")
            dir_to_resources = path.join(dir_to_temp, 'resources')

            shutil.copytree(path.join(dir_to_root, 'shell_resources'), path.join(dir_to_resources, 'shell_resources'))
            shutil.copytree(path.join(dir_to_root, 'servo_resources'), path.join(dir_to_resources, 'servo_resources'))

            shutil.copy(binary_path, dir_to_temp)

            print("Creating tarball")
            tar_path = path.join(target_dir, 'servoshell.tar.gz')

            archive_deterministically(dir_to_temp, tar_path, prepend_path='servoshell/')

            print("Cleaning up")
            delete(dir_to_temp)
            print("Packaged ServoShell into " + tar_path)