mirror of
https://github.com/facebook/proxygen.git
synced 2025-08-10 05:22:59 +03:00
Summary: While the command isn't necessarily super useful on its own, it does show that the plumbing for walking the deps is functioning, and that is important when it comes to building. The output lists the projects in the order that they would be built. The `fetch` command has been augmented to add a `--recursive` flag that uses the same mechanism to recursively fetch the dependencies. Reviewed By: simpkins Differential Revision: D14691004 fbshipit-source-id: b00bf6ad4742f8bb0a70698f71a5fe03d6a1f453
95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
# Copyright (c) 2019-present, Facebook, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This source code is licensed under the BSD-style license found in the
|
|
# LICENSE file in the root directory of this source tree. An additional grant
|
|
# of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
import os
|
|
|
|
from .manifest import ManifestParser
|
|
|
|
|
|
def resolve_manifest_path(build_opts, project_name):
|
|
if "/" in project_name or "\\" in project_name:
|
|
# Assume this is a path already
|
|
return project_name
|
|
|
|
# Otherwise, resolve it relative to the manifests dir
|
|
return os.path.join(build_opts.fbcode_builder_dir, "manifests", project_name)
|
|
|
|
|
|
def load_project(build_opts, project_name):
|
|
""" given the name of a project or a path to a manifest file,
|
|
load up the ManifestParser instance for it and return it """
|
|
manifest_path = resolve_manifest_path(build_opts, project_name)
|
|
return ManifestParser(manifest_path)
|
|
|
|
|
|
def manifests_in_dependency_order(build_opts, manifest, ctx):
|
|
""" Given a manifest, expand its dependencies and return a list
|
|
of the manifest objects that would need to be built in the order
|
|
that they would need to be built. This does not evaluate whether
|
|
a build is needed; it just returns the list in the order specified
|
|
by the manifest files. """
|
|
# A dict to save loading a project multiple times
|
|
manifests_by_name = {manifest.name: manifest}
|
|
# The list of deps that have been fully processed
|
|
seen = set()
|
|
# The list of deps which have yet to be evaluated. This
|
|
# can potentially contain duplicates.
|
|
deps = [manifest]
|
|
# The list of manifests in dependency order
|
|
dep_order = []
|
|
|
|
while len(deps) > 0:
|
|
m = deps.pop(0)
|
|
if m.name in seen:
|
|
continue
|
|
|
|
# Consider its deps, if any.
|
|
# We sort them for increased determinism; we'll produce
|
|
# a correct order even if they aren't sorted, but we prefer
|
|
# to produce the same order regardless of how they are listed
|
|
# in the project manifest files.
|
|
dep_list = sorted(m.get_section_as_dict("dependencies", ctx).keys())
|
|
builder = m.get("build", "builder", ctx=ctx)
|
|
if builder == "cmake":
|
|
dep_list.append("cmake")
|
|
elif builder == "autoconf" and m.name not in (
|
|
"autoconf",
|
|
"libtool",
|
|
"automake",
|
|
):
|
|
# they need libtool and its deps (automake, autoconf) so add
|
|
# those as deps (but obviously not if we're building those
|
|
# projects themselves)
|
|
dep_list.append("libtool")
|
|
|
|
dep_count = 0
|
|
for dep in dep_list:
|
|
# If we're not sure whether it is done, queue it up
|
|
if dep not in seen:
|
|
if dep not in manifests_by_name:
|
|
dep = load_project(build_opts, dep)
|
|
manifests_by_name[dep.name] = dep
|
|
else:
|
|
dep = manifests_by_name[dep]
|
|
|
|
deps.append(dep)
|
|
dep_count += 1
|
|
|
|
if dep_count > 0:
|
|
# If we queued anything, re-queue this item, as it depends
|
|
# those new item(s) and their transitive deps.
|
|
deps.append(m)
|
|
continue
|
|
|
|
# Its deps are done, so we can emit it
|
|
seen.add(m.name)
|
|
dep_order.append(m)
|
|
|
|
return dep_order
|