Skip to main content
Glama
transitive_dependency_symlinks.py3.46 kB
#!/usr/bin/env python3 # Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under both the MIT license found in the # LICENSE-MIT file in the root directory of this source tree and the Apache # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. # A tool to produce a directory structure compatible with rustc's `-Ldependency` # flag for dynamically named crates. # # Rustc needs all the .rlib files which are transitive dependencies of the crate # being built. Importantly, the filename for each rlib must contain the correct # crate name or else rustc won't find the file. # # Most crates have a crate name determined during analysis: value of the `crate` # attribute, or derived using a simple heuristic from the rust_library target's # `name` attribute. For these it's easy to give the rlib a correct filename up # front and use buck's `ctx.actions.symlinked_dir` to collect them into a # directory. These do not go through this tool. # # Crates that use `crate_dynamic` have a crate name computed at build time, for # example by extracting the name from a .thrift file. Buck needs a filename at # analysis time for all artifacts, so we name those rlib files using a # provisional name and then this tool at build time will symlink them under the # real crate name that rustc will recognize. # # Example: # # transitive_dependency_symlinks.py \ # --out-dir path/to/out \ # --artifacts path/to/artifacts.json # # The input file artifact.json is an array of pairs, each an rlib and a file # containing a crate name for it. # # [ # ["../../libprovisional.rlib", "path/to/cratename"], # ... # ] # # The tool reads the crate name from the file at "path/to/cratename". Suppose it's # "thriftgenerated". It symlinks the given artifact as "0/libthriftgenerated.rlib" # within the specified output directory. In the event of collisions, there might # be multiple dirs created, just as we do for analysis-time named crates. import argparse import json import os from pathlib import Path from typing import IO, NamedTuple class Args(NamedTuple): out_dir: Path artifacts: IO[str] def main(): parser = argparse.ArgumentParser() parser.add_argument( "--out-dir", type=Path, required=True, ) parser.add_argument( "--artifacts", type=argparse.FileType(), required=True, ) args = Args(**vars(parser.parse_args())) args.out_dir.mkdir(exist_ok=True) # Add as many -Ldependency dirs as we need to avoid name conflicts deps_dirs = [{}] for artifact, crate_name in json.load(args.artifacts): crate_name = Path(crate_name).read_text().strip() original_filename = os.path.basename(artifact) new_filename = "lib{}-{}".format( crate_name, original_filename.rsplit("-", 1)[1], ) if new_filename in deps_dirs[-1]: deps_dirs.append({}) deps_dirs[-1][new_filename] = artifact flags = "" for idx, srcs in enumerate(deps_dirs): directory = args.out_dir.joinpath(str(idx)) directory.mkdir() flags += "-Ldependency={}\n".format(directory) for filename, artifact in srcs.items(): directory.joinpath(filename).symlink_to(artifact) args.out_dir.joinpath("dirs").write_text(flags) if __name__ == "__main__": main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server