Example #1
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)

        ctx = context_from_host_tuple()
        ctx["test"] = "on"
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        # Accumulate the install directories so that the test steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            fetcher = m.create_fetcher(opts, ctx)

            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            build_dir = dirs["build_dir"]
            inst_dir = dirs["inst_dir"]

            if m == manifest or args.test_all:
                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if not os.path.exists(built_marker):
                    print("project %s has not been built" % m.name)
                    # TODO: we could just go ahead and build it here, but I
                    # want to tackle that as part of adding build-for-test
                    # support.
                    return 1
                src_dir = fetcher.get_src_dir()
                builder = m.create_builder(opts, src_dir, build_dir, inst_dir,
                                           ctx)
                builder.run_tests(install_dirs)

            install_dirs.append(inst_dir)
Example #2
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)

        ctx = context_from_host_tuple()
        ctx["test"] = "on"
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        # Accumulate the install directories so that the test steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            fetcher = m.create_fetcher(opts, ctx)

            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            build_dir = dirs["build_dir"]
            inst_dir = dirs["inst_dir"]

            if m == manifest or args.test_all:
                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if not os.path.exists(built_marker):
                    print("project %s has not been built" % m.name)
                    # TODO: we could just go ahead and build it here, but I
                    # want to tackle that as part of adding build-for-test
                    # support.
                    return 1
                src_dir = fetcher.get_src_dir()
                builder = m.create_builder(opts, src_dir, build_dir, inst_dir, ctx)
                builder.run_tests(install_dirs)

            install_dirs.append(inst_dir)
Example #3
0
 def run(self, args):
     opts = setup_build_options(args)
     manifest = load_project(opts, args.project)
     ctx = context_from_host_tuple(args.host_type)
     for m in manifests_in_dependency_order(opts, manifest, ctx):
         print(m.name)
     return 0
Example #4
0
    def run(self, args):
        opts = setup_build_options(args)

        manifest = load_project(opts, args.project)

        ctx = context_from_host_tuple(facebook_internal=args.facebook_internal)
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        # Accumulate the install directories so that the build steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            ctx = dict(ctx)
            if args.enable_tests and m.name == manifest.name:
                ctx["test"] = "on"
            else:
                ctx["test"] = "off"
            fetcher = m.create_fetcher(opts, ctx)

            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            inst_dir = dirs["inst_dir"]

            install_dirs.append(inst_dir)

            if m == manifest:
                dep_munger = create_dyn_dep_munger(opts, install_dirs)
                dep_munger.process_deps(args.destdir,
                                        args.final_install_prefix)
Example #5
0
 def run(self, args):
     opts = setup_build_options(args)
     manifest = load_project(opts, args.project)
     ctx = context_from_host_tuple(args.host_type)
     for m in manifests_in_dependency_order(opts, manifest, ctx):
         print(m.name)
     return 0
Example #6
0
    def run(self, args):
        opts = setup_build_options(args)

        if args.current_project is not None:
            opts.repo_project = args.current_project
        if args.project is None:
            if opts.repo_project is None:
                raise UsageError(
                    "no project name specified, and no .projectid file found")
            if opts.repo_project == "fbsource":
                # The fbsource repository is a little special.  There is no project
                # manifest file for it.  A specific project must always be explicitly
                # specified when building from fbsource.
                raise UsageError(
                    "no project name specified (required when building in fbsource)"
                )
            args.project = opts.repo_project

        ctx_gen = opts.get_context_generator(
            facebook_internal=args.facebook_internal)
        if args.test_dependencies:
            ctx_gen.set_value_for_all_projects("test", "on")
        if args.enable_tests:
            ctx_gen.set_value_for_project(args.project, "test", "on")
        else:
            ctx_gen.set_value_for_project(args.project, "test", "off")

        loader = ManifestLoader(opts, ctx_gen)
        self.process_project_dir_arguments(args, loader)

        manifest = loader.load_manifest(args.project)

        self.run_project_cmd(args, loader, manifest)
Example #7
0
    def run(self, args):
        opts = setup_build_options(args)
        if args.clean:
            clean_dirs(opts)

        manifest = load_project(opts, args.project)

        ctx = context_from_host_tuple()
        print("Building on %s" % ctx)
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        # Accumulate the install directories so that the build steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            ctx = dict(ctx)
            if args.enable_tests and m.name == manifest.name:
                ctx["test"] = "on"
            else:
                ctx["test"] = "off"
            fetcher = m.create_fetcher(opts, ctx)

            if args.clean:
                fetcher.clean()

            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            build_dir = dirs["build_dir"]
            inst_dir = dirs["inst_dir"]

            if m == manifest or not args.no_deps:
                print("Assessing %s..." % m.name)
                change_status = fetcher.update()
                reconfigure = change_status.build_changed()
                sources_changed = change_status.sources_changed()

                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if os.path.exists(built_marker):
                    with open(built_marker, "r") as f:
                        built_hash = f.read().strip()
                    if built_hash != dirs["hash"]:
                        # Some kind of inconsistency with a prior build,
                        # let's run it again to be sure
                        os.unlink(built_marker)
                        reconfigure = True

                if sources_changed or reconfigure or not os.path.exists(
                        built_marker):
                    if os.path.exists(built_marker):
                        os.unlink(built_marker)
                    src_dir = fetcher.get_src_dir()
                    builder = m.create_builder(opts, src_dir, build_dir,
                                               inst_dir, ctx)
                    builder.build(install_dirs, reconfigure=reconfigure)

                    with open(built_marker, "w") as f:
                        f.write(dirs["hash"])

            install_dirs.append(inst_dir)
Example #8
0
    def run_project_cmd(self, args, loader, manifest):
        platforms = [
            HostType("linux", "ubuntu", "18"),
            HostType("darwin", None, None),
            HostType("windows", None, None),
        ]

        with open(args.output_file, "w") as out:
            # Deliberate line break here because the @ and the generated
            # symbols are meaningful to our internal tooling when they
            # appear in a single token
            out.write("# This file was @")
            out.write("generated by getdeps.py\n")
            out.write("""
name: CI

on:
  push:
    branches:
    - master
  pull_request:
    branches:
    - master

jobs:
""")
            for p in platforms:
                build_opts = setup_build_options(args, p)
                self.write_job_for_platform(out, args, build_opts)
Example #9
0
    def run(self, args):
        opts = setup_build_options(args)
        ctx_gen = opts.get_context_generator(facebook_internal=args.facebook_internal)
        if args.test_all:
            ctx_gen.set_value_for_all_projects("test", "on")
        else:
            ctx_gen.set_value_for_project(args.project, "test", "on")

        loader = ManifestLoader(opts, ctx_gen)
        manifest = loader.load_manifest(args.project)
        projects = loader.manifests_in_dependency_order()

        # Accumulate the install directories so that the test steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            inst_dir = loader.get_project_install_dir(m)

            if m == manifest or args.test_all:
                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if not os.path.exists(built_marker):
                    print("project %s has not been built" % m.name)
                    # TODO: we could just go ahead and build it here, but I
                    # want to tackle that as part of adding build-for-test
                    # support.
                    return 1
                fetcher = loader.create_fetcher(m)
                src_dir = fetcher.get_src_dir()
                ctx = ctx_gen.get_context(m.name)
                build_dir = loader.get_project_build_dir(m)
                builder = m.create_builder(opts, src_dir, build_dir, inst_dir, ctx)
                builder.run_tests(install_dirs, schedule_type=args.schedule_type)

            install_dirs.append(inst_dir)
Example #10
0
 def run(self, args):
     opts = setup_build_options(args)
     loader = ManifestLoader(opts)
     loader.ctx_gen.set_value_for_project(args.project, "test", "on")
     loader.load_manifest(args.project)
     for m in loader.manifests_in_dependency_order():
         print(m.name)
     return 0
Example #11
0
    def run(self, args):
        opts = setup_build_options(args)
        if args.clean:
            clean_dirs(opts)

        manifest = load_project(opts, args.project)

        ctx = context_from_host_tuple()
        print("Building on %s" % ctx)
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        # Accumulate the install directories so that the build steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            ctx = dict(ctx)
            if args.enable_tests and m.name == manifest.name:
                ctx["test"] = "on"
            else:
                ctx["test"] = "off"
            fetcher = m.create_fetcher(opts, ctx)

            if args.clean:
                fetcher.clean()

            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            build_dir = dirs["build_dir"]
            inst_dir = dirs["inst_dir"]

            if m == manifest or not args.no_deps:
                print("Assessing %s..." % m.name)
                change_status = fetcher.update()
                reconfigure = change_status.build_changed()
                sources_changed = change_status.sources_changed()

                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if os.path.exists(built_marker):
                    with open(built_marker, "r") as f:
                        built_hash = f.read().strip()
                    if built_hash != dirs["hash"]:
                        # Some kind of inconsistency with a prior build,
                        # let's run it again to be sure
                        os.unlink(built_marker)
                        reconfigure = True

                if sources_changed or reconfigure or not os.path.exists(built_marker):
                    if os.path.exists(built_marker):
                        os.unlink(built_marker)
                    src_dir = fetcher.get_src_dir()
                    builder = m.create_builder(opts, src_dir, build_dir, inst_dir, ctx)
                    builder.build(install_dirs, reconfigure=reconfigure)

                    with open(built_marker, "w") as f:
                        f.write(dirs["hash"])

            install_dirs.append(inst_dir)
Example #12
0
    def run(self, args):
        opts = setup_build_options(args)
        ctx_gen = opts.get_context_generator(facebook_internal=args.facebook_internal)
        if args.enable_tests:
            ctx_gen.set_value_for_project(args.project, "test", "on")
        loader = ManifestLoader(opts, ctx_gen)

        if args.clean:
            clean_dirs(opts)

        manifest = loader.load_manifest(args.project)

        print("Building on %s" % ctx_gen.get_context(args.project))
        projects = loader.manifests_in_dependency_order()

        # Accumulate the install directories so that the build steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            fetcher = loader.create_fetcher(m)

            if args.clean:
                fetcher.clean()

            build_dir = loader.get_project_build_dir(m)
            inst_dir = loader.get_project_install_dir(m)

            if m == manifest or not args.no_deps:
                print("Assessing %s..." % m.name)
                change_status = fetcher.update()
                reconfigure = change_status.build_changed()
                sources_changed = change_status.sources_changed()

                project_hash = loader.get_project_hash(m)
                built_marker = os.path.join(inst_dir, ".built-by-getdeps")
                if os.path.exists(built_marker):
                    with open(built_marker, "r") as f:
                        built_hash = f.read().strip()
                    if built_hash != project_hash:
                        # Some kind of inconsistency with a prior build,
                        # let's run it again to be sure
                        os.unlink(built_marker)
                        reconfigure = True

                if sources_changed or reconfigure or not os.path.exists(built_marker):
                    if os.path.exists(built_marker):
                        os.unlink(built_marker)
                    src_dir = fetcher.get_src_dir()
                    ctx = ctx_gen.get_context(m.name)
                    builder = m.create_builder(opts, src_dir, build_dir, inst_dir, ctx)
                    builder.build(install_dirs, reconfigure=reconfigure)

                    with open(built_marker, "w") as f:
                        f.write(project_hash)

            install_dirs.append(inst_dir)
Example #13
0
 def run(self, args):
     opts = setup_build_options(args)
     manifest = load_project(opts, args.project)
     ctx = context_from_host_tuple(args.host_type)
     if args.recursive:
         projects = manifests_in_dependency_order(opts, manifest, ctx)
     else:
         projects = [manifest]
     for m in projects:
         fetcher = m.create_fetcher(opts, ctx)
         fetcher.update()
Example #14
0
 def run(self, args):
     opts = setup_build_options(args)
     loader = ManifestLoader(opts)
     manifest = loader.load_manifest(args.project)
     if args.recursive:
         projects = loader.manifests_in_dependency_order()
     else:
         projects = [manifest]
     for m in projects:
         fetcher = loader.create_fetcher(m)
         fetcher.update()
Example #15
0
 def run(self, args):
     opts = setup_build_options(args)
     manifest = load_project(opts, args.project)
     ctx = context_from_host_tuple(args.host_type)
     if args.recursive:
         projects = manifests_in_dependency_order(opts, manifest, ctx)
     else:
         projects = [manifest]
     for m in projects:
         fetcher = m.create_fetcher(opts, ctx)
         fetcher.update()
Example #16
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)
        ctx = context_from_host_tuple()

        if args.recursive:
            manifests = manifests_in_dependency_order(opts, manifest, ctx)
        else:
            manifests = [manifest]

        for m in manifests:
            fetcher = m.create_fetcher(opts, ctx)
            print(fetcher.get_src_dir())
Example #17
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)
        ctx = context_from_host_tuple()

        if args.recursive:
            manifests = manifests_in_dependency_order(opts, manifest, ctx)
        else:
            manifests = [manifest]

        for m in manifests:
            fetcher = m.create_fetcher(opts, ctx)
            print(fetcher.get_src_dir())
Example #18
0
    def run(self, args):
        opts = setup_build_options(args)
        loader = ManifestLoader(opts)
        loader.ctx_gen.set_value_for_project(args.project, "test", "on")
        manifest = loader.load_manifest(args.project)

        if args.recursive:
            manifests = loader.manifests_in_dependency_order()
        else:
            manifests = [manifest]

        for m in manifests:
            fetcher = loader.create_fetcher(m)
            print(fetcher.get_src_dir())
Example #19
0
    def run(self, args):
        opts = setup_build_options(args)
        loader = ManifestLoader(opts)
        loader.ctx_gen.set_value_for_project(args.project, "test", "on")
        manifest = loader.load_manifest(args.project)
        projects = loader.manifests_in_dependency_order()

        if args.recursive:
            manifests = projects
        else:
            manifests = [manifest]

        for m in manifests:
            inst_dir = loader.get_project_install_dir(m)
            print(inst_dir)
Example #20
0
    def run(self, args):
        opts = setup_build_options(args)
        ctx_gen = opts.get_context_generator(facebook_internal=args.facebook_internal)
        if args.test_dependencies:
            ctx_gen.set_value_for_all_projects("test", "on")
        if args.enable_tests:
            ctx_gen.set_value_for_project(args.project, "test", "on")
        else:
            ctx_gen.set_value_for_project(args.project, "test", "off")

        loader = ManifestLoader(opts, ctx_gen)
        self.process_project_dir_arguments(args, loader)

        manifest = loader.load_manifest(args.project)

        self.run_project_cmd(args, loader, manifest)
Example #21
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)
        ctx = context_from_host_tuple()
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        if args.recursive:
            manifests = projects
        else:
            manifests = [manifest]

        for m in manifests:
            fetcher = m.create_fetcher(opts, ctx)
            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            inst_dir = dirs["inst_dir"]
            print(inst_dir)
Example #22
0
    def run(self, args):
        opts = setup_build_options(args)
        manifest = load_project(opts, args.project)
        ctx = context_from_host_tuple()
        projects = manifests_in_dependency_order(opts, manifest, ctx)
        manifests_by_name = {m.name: m for m in projects}

        if args.recursive:
            manifests = projects
        else:
            manifests = [manifest]

        for m in manifests:
            fetcher = m.create_fetcher(opts, ctx)
            dirs = opts.compute_dirs(m, fetcher, manifests_by_name, ctx)
            inst_dir = dirs["inst_dir"]
            print(inst_dir)
Example #23
0
    def run(self, args):
        opts = setup_build_options(args)
        ctx_gen = opts.get_context_generator(facebook_internal=args.facebook_internal)
        if args.enable_tests:
            ctx_gen.set_value_for_project(args.project, "test", "on")

        loader = ManifestLoader(opts, ctx_gen)
        manifest = loader.load_manifest(args.project)

        projects = loader.manifests_in_dependency_order()

        # Accumulate the install directories so that the build steps
        # can find their dep installation
        install_dirs = []

        for m in projects:
            inst_dir = loader.get_project_install_dir(m)
            install_dirs.append(inst_dir)

            if m == manifest:
                dep_munger = create_dyn_dep_munger(opts, install_dirs)
                dep_munger.process_deps(args.destdir, args.final_install_prefix)
Example #24
0
 def run(self, args):
     opts = setup_build_options(args)
     clean_dirs(opts)
Example #25
0
    def write_job_for_platform(self, platform, args):  # noqa: C901
        build_opts = setup_build_options(args, platform)
        ctx_gen = build_opts.get_context_generator()
        loader = ManifestLoader(build_opts, ctx_gen)
        manifest = loader.load_manifest(args.project)
        manifest_ctx = loader.ctx_gen.get_context(manifest.name)
        run_on = self.get_run_on(args)

        # Some projects don't do anything "useful" as a leaf project, only
        # as a dep for a leaf project. Check for those here; we don't want
        # to waste the effort scheduling them on CI.
        # We do this by looking at the builder type in the manifest file
        # rather than creating a builder and checking its type because we
        # don't know enough to create the full builder instance here.
        if manifest.get("build", "builder", ctx=manifest_ctx) == "nop":
            return None

        # We want to be sure that we're running things with python 3
        # but python versioning is honestly a bit of a frustrating mess.
        # `python` may be version 2 or version 3 depending on the system.
        # python3 may not be a thing at all!
        # Assume an optimistic default
        py3 = "python3"

        if build_opts.is_linux():
            artifacts = "linux"
            runs_on = f"ubuntu-{args.ubuntu_version}"
        elif build_opts.is_windows():
            artifacts = "windows"
            runs_on = "windows-2019"
            # The windows runners are python 3 by default; python2.exe
            # is available if needed.
            py3 = "python"
        else:
            artifacts = "mac"
            runs_on = "macOS-latest"

        os.makedirs(args.output_dir, exist_ok=True)

        job_file_prefix = "getdeps_"
        if args.job_file_prefix:
            job_file_prefix = args.job_file_prefix

        output_file = os.path.join(args.output_dir,
                                   f"{job_file_prefix}{artifacts}.yml")

        if args.job_name_prefix:
            job_name = args.job_name_prefix + artifacts.capitalize()
        else:
            job_name = artifacts

        with open(output_file, "w") as out:
            # Deliberate line break here because the @ and the generated
            # symbols are meaningful to our internal tooling when they
            # appear in a single token
            out.write("# This file was @")
            out.write("generated by getdeps.py\n")
            out.write(f"""
name: {job_name}

on:{run_on}

jobs:
""")

            getdepscmd = f"{py3} build/fbcode_builder/getdeps.py"

            out.write("  build:\n")
            out.write("    runs-on: %s\n" % runs_on)
            out.write("    steps:\n")
            out.write("    - uses: actions/checkout@v2\n")

            if build_opts.is_windows():
                # cmake relies on BOOST_ROOT but GH deliberately don't set it in order
                # to avoid versioning issues:
                # https://github.com/actions/virtual-environments/issues/319
                # Instead, set the version we think we need; this is effectively
                # coupled with the boost manifest
                # This is the unusual syntax for setting an env var for the rest of
                # the steps in a workflow:
                # https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
                out.write("    - name: Export boost environment\n")
                out.write(
                    '      run: "echo BOOST_ROOT=%BOOST_ROOT_1_78_0% >> %GITHUB_ENV%"\n'
                )
                out.write("      shell: cmd\n")

                # The git installation may not like long filenames, so tell it
                # that we want it to use them!
                out.write("    - name: Fix Git config\n")
                out.write(
                    "      run: git config --system core.longpaths true\n")

            allow_sys_arg = ""
            if (build_opts.allow_system_packages
                    and build_opts.host_type.get_package_manager()):
                sudo_arg = "sudo "
                allow_sys_arg = " --allow-system-packages"
                if build_opts.host_type.get_package_manager() == "deb":
                    out.write("    - name: Update system package info\n")
                    out.write(f"      run: {sudo_arg}apt-get update\n")

                out.write("    - name: Install system deps\n")
                if build_opts.is_darwin():
                    # brew is installed as regular user
                    sudo_arg = ""
                out.write(
                    f"      run: {sudo_arg}python3 build/fbcode_builder/getdeps.py --allow-system-packages install-system-deps --recursive {manifest.name}\n"
                )

            projects = loader.manifests_in_dependency_order()

            main_repo_url = manifest.get_repo_url(manifest_ctx)
            has_same_repo_dep = False

            for m in projects:
                if m != manifest:
                    if m.name == "rust":
                        out.write("    - name: Install Rust Stable\n")
                        out.write("      uses: actions-rs/toolchain@v1\n")
                        out.write("      with:\n")
                        out.write("        toolchain: stable\n")
                        out.write("        default: true\n")
                        out.write("        profile: minimal\n")
                    else:
                        ctx = loader.ctx_gen.get_context(m.name)
                        if m.get_repo_url(ctx) != main_repo_url:
                            out.write("    - name: Fetch %s\n" % m.name)
                            out.write(
                                f"      run: {getdepscmd}{allow_sys_arg} fetch --no-tests {m.name}\n"
                            )

            for m in projects:
                if m != manifest:
                    if m.name == "rust":
                        continue
                    else:
                        src_dir_arg = ""
                        ctx = loader.ctx_gen.get_context(m.name)
                        if main_repo_url and m.get_repo_url(
                                ctx) == main_repo_url:
                            # Its in the same repo, so src-dir is also .
                            src_dir_arg = "--src-dir=. "
                            has_same_repo_dep = True
                        out.write("    - name: Build %s\n" % m.name)
                        out.write(
                            f"      run: {getdepscmd}{allow_sys_arg} build {src_dir_arg}--no-tests {m.name}\n"
                        )

            out.write("    - name: Build %s\n" % manifest.name)

            project_prefix = ""
            if not build_opts.is_windows():
                project_prefix = (" --project-install-prefix %s:/usr/local" %
                                  manifest.name)

            # If we have dep from same repo, we already built it and don't want to rebuild it again
            no_deps_arg = ""
            if has_same_repo_dep:
                no_deps_arg = "--no-deps "

            out.write(
                f"      run: {getdepscmd}{allow_sys_arg} build {no_deps_arg}--src-dir=. {manifest.name} {project_prefix}\n"
            )

            out.write("    - name: Copy artifacts\n")
            if build_opts.is_linux():
                # Strip debug info from the binaries, but only on linux.
                # While the `strip` utility is also available on macOS,
                # attempting to strip there results in an error.
                # The `strip` utility is not available on Windows.
                strip = " --strip"
            else:
                strip = ""

            out.write(
                f"      run: {getdepscmd}{allow_sys_arg} fixup-dyn-deps{strip} "
                f"--src-dir=. {manifest.name} _artifacts/{artifacts} {project_prefix} "
                f"--final-install-prefix /usr/local\n")

            out.write("    - uses: actions/upload-artifact@v2\n")
            out.write("      with:\n")
            out.write("        name: %s\n" % manifest.name)
            out.write("        path: _artifacts\n")

            if manifest.get("github.actions", "run_tests",
                            ctx=manifest_ctx) != "off":
                out.write("    - name: Test %s\n" % manifest.name)
                out.write(
                    f"      run: {getdepscmd}{allow_sys_arg} test --src-dir=. {manifest.name} {project_prefix}\n"
                )
Example #26
0
    def write_job_for_platform(self, platform, args):
        build_opts = setup_build_options(args, platform)
        ctx_gen = build_opts.get_context_generator()
        loader = ManifestLoader(build_opts, ctx_gen)
        manifest = loader.load_manifest(args.project)
        manifest_ctx = loader.ctx_gen.get_context(manifest.name)

        # Some projects don't do anything "useful" as a leaf project, only
        # as a dep for a leaf project.  Check for those here; we don't want
        # to waste the effort scheduling them on CI.
        # We do this by looking at the builder type in the manifest file
        # rather than creating a builder and checking its type because we
        # don't know enough to create the full builder instance here.
        if manifest.get("build", "builder", ctx=manifest_ctx) == "nop":
            return None

        # We want to be sure that we're running things with python 3
        # but python versioning is honestly a bit of a frustrating mess.
        # `python` may be version 2 or version 3 depending on the system.
        # python3 may not be a thing at all!
        # Assume an optimistic default
        py3 = "python3"

        if build_opts.is_linux():
            job_name = "linux"
            runs_on = "ubuntu-18.04"
        elif build_opts.is_windows():
            # We're targeting the windows-2016 image because it has
            # Visual Studio 2017 installed, and at the time of writing,
            # the version of boost in the manifests (1.69) is not
            # buildable with Visual Studio 2019
            job_name = "windows"
            runs_on = "windows-2016"
            # The windows runners are python 3 by default; python2.exe
            # is available if needed.
            py3 = "python"
        else:
            job_name = "mac"
            runs_on = "macOS-latest"

        os.makedirs(args.output_dir, exist_ok=True)
        output_file = os.path.join(args.output_dir, f"getdeps_{job_name}.yml")
        with open(output_file, "w") as out:
            # Deliberate line break here because the @ and the generated
            # symbols are meaningful to our internal tooling when they
            # appear in a single token
            out.write("# This file was @")
            out.write("generated by getdeps.py\n")
            out.write(f"""
name: {job_name}

on:
  push:
    branches:
    - master
  pull_request:
    branches:
    - master

jobs:
""")

            getdeps = f"{py3} build/fbcode_builder/getdeps.py --allow-system-packages"

            out.write("  build:\n")
            out.write("    runs-on: %s\n" % runs_on)
            out.write("    steps:\n")
            out.write("    - uses: actions/checkout@v1\n")

            if build_opts.is_windows():
                # cmake relies on BOOST_ROOT but GH deliberately don't set it in order
                # to avoid versioning issues:
                # https://github.com/actions/virtual-environments/issues/319
                # Instead, set the version we think we need; this is effectively
                # coupled with the boost manifest
                # This is the unusual syntax for setting an env var for the rest of
                # the steps in a workflow:
                # https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
                out.write("    - name: Export boost environment\n")
                out.write(
                    '      run: "echo ::set-env name=BOOST_ROOT::%BOOST_ROOT_1_69_0%"\n'
                )
                out.write("      shell: cmd\n")

                # The git installation may not like long filenames, so tell it
                # that we want it to use them!
                out.write("    - name: Fix Git config\n")
                out.write(
                    "      run: git config --system core.longpaths true\n")
            else:
                out.write("    - name: Install system deps\n")
                out.write(
                    f"      run: sudo {getdeps} install-system-deps --recursive {manifest.name}\n"
                )

            projects = loader.manifests_in_dependency_order()

            for m in projects:
                if m != manifest:
                    out.write("    - name: Fetch %s\n" % m.name)
                    out.write(
                        f"      run: {getdeps} fetch --no-tests {m.name}\n")

            for m in projects:
                if m != manifest:
                    out.write("    - name: Build %s\n" % m.name)
                    out.write(
                        f"      run: {getdeps} build --no-tests {m.name}\n")

            out.write("    - name: Build %s\n" % manifest.name)

            project_prefix = ""
            if not build_opts.is_windows():
                project_prefix = (" --project-install-prefix %s:/usr/local" %
                                  manifest.name)

            out.write(
                f"      run: {getdeps} build --src-dir=. {manifest.name} {project_prefix}\n"
            )

            out.write("    - name: Copy artifacts\n")
            if build_opts.is_linux():
                # Strip debug info from the binaries, but only on linux.
                # While the `strip` utility is also available on macOS,
                # attempting to strip there results in an error.
                # The `strip` utility is not available on Windows.
                strip = " --strip"
            else:
                strip = ""

            out.write(
                f"      run: {getdeps} fixup-dyn-deps{strip} "
                f"--src-dir=. {manifest.name} _artifacts/{job_name} {project_prefix} "
                f"--final-install-prefix /usr/local\n")

            out.write("    - uses: actions/upload-artifact@master\n")
            out.write("      with:\n")
            out.write("        name: %s\n" % manifest.name)
            out.write("        path: _artifacts\n")

            out.write("    - name: Test %s\n" % manifest.name)
            out.write(
                f"      run: {getdeps} test --src-dir=. {manifest.name} {project_prefix}\n"
            )
Example #27
0
 def run(self, args):
     opts = setup_build_options(args)
     clean_dirs(opts)