{"id":13450795,"url":"https://github.com/cgrushko/tools_jvm_autodeps","last_synced_at":"2025-03-23T16:32:15.369Z","repository":{"id":57515586,"uuid":"126338656","full_name":"cgrushko/tools_jvm_autodeps","owner":"cgrushko","description":"Automatic Dependency Management Tools for JVM Languages","archived":false,"fork":false,"pushed_at":"2019-01-30T13:39:21.000Z","size":233,"stargazers_count":53,"open_issues_count":14,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-15T08:57:34.753Z","etag":null,"topics":["bazel","dependencies","deps","java","jvm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cgrushko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-22T13:23:15.000Z","updated_at":"2025-03-09T19:31:11.000Z","dependencies_parsed_at":"2022-08-29T20:22:09.427Z","dependency_job_id":null,"html_url":"https://github.com/cgrushko/tools_jvm_autodeps","commit_stats":null,"previous_names":["bazelbuild/tools_jvm_autodeps"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgrushko%2Ftools_jvm_autodeps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgrushko%2Ftools_jvm_autodeps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgrushko%2Ftools_jvm_autodeps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgrushko%2Ftools_jvm_autodeps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cgrushko","download_url":"https://codeload.github.com/cgrushko/tools_jvm_autodeps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245130992,"owners_count":20565755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bazel","dependencies","deps","java","jvm"],"created_at":"2024-07-31T07:00:38.625Z","updated_at":"2025-03-23T16:32:15.054Z","avatar_url":"https://github.com/cgrushko.png","language":"Go","funding_links":[],"categories":["Tooling"],"sub_categories":["Project generators"],"readme":"# Java Automatic Dependencies (Jadep)\n\nJadep is a [Bazel](http://bazel.build) `BUILD` file generator for Java projects. It adds `BUILD`\ndependencies that a Java file needs, aiming for \u003c1s response times.\n\nJadep is intended to manage `BUILD` files for your own code in the current Bazel workspace (as opposed to BUILD files for third-party libraries).\n\nJadep is not an official Google product.\n\n[![Build status](https://badge.buildkite.com/38a87d1503f25d2cf22f75eed28b43318b91cb1a59f3d33aa3.svg)](https://buildkite.com/bazel/tools-jvm-autodeps)\n\n[![demo](https://asciinema.org/a/ojpEKcVoC1I0QHcJNBjkfi7AO.png)](https://asciinema.org/a/ojpEKcVoC1I0QHcJNBjkfi7AO?autoplay=1)\n\n**Contents**\n\n- [Java Automatic Dependencies (Jadep)](#java-automatic-dependencies-jadep)\n    - [Usage](#usage)\n    - [Detailed Example: Migrating a Java project to Bazel](#detailed-example--migrating-a-java-project-to-bazel)\n    - [Building / Installation](#building---installation)\n    - [How does it Work?](#how-does-it-work)\n        - [Detailed Flow](#detailed-flow)\n        - [Extracting Class Names](#extracting-class-names)\n        - [Resolver: File System](#resolver--file-system)\n        - [Resolver: JDK / Android SDK](#resolver--jdk---android-sdk)\n        - [Reading `BUILD` files](#reading-build-files)\n    - [Extending / Hacking / Future Ideas](#extending---hacking---future-ideas)\n    - [Bugs](#bugs)\n    - [Contributing](#contributing)\n\n## Usage\n\n```\n~/bin/jadep path/to/File.java\n```\n\n## Detailed Example: Migrating a Java project to Bazel\n\n\u003chttps://github.com/cgrushko/text/blob/master/migrating-gjf-to-bazel.md\u003e\n\n## Building / Installation\n\nThe following will build Jadep and its persistent server, and will copy them to\n`~/bin/` and `~/jadep/`.\n\n```bash\n# Jadep\nmkdir -p ~/bin\nmkdir -p ~/jadep\n\nbazel build -c opt //cmd/jadep\n\njadep=( bazel-bin/cmd/jadep/*/jadep ) # work around https://github.com/bazelbuild/rules_go/issues/1239\ncp \"${jadep[0]}\" ~/bin/\n\n# PackageLoader server\nbazel build -c opt --nocheck_visibility //java/com/google/devtools/javatools/jade/pkgloader:GrpcLocalServer_deploy.jar\n\ncp bazel-bin/java/com/google/devtools/javatools/jade/pkgloader/GrpcLocalServer_deploy.jar ~/jadep/\ncp scripts/pkgloader_server.sh ~/jadep/\n\n# JDK symbols [Jadep can run without these]\nbazel build //:jdk_android_builtin_class_names\n\ncp bazel-genfiles/jdk_android_builtin_class_names.txt ~/jadep/\n```\n\n## How does it Work?\n\nAfter parsing a Java file, Jadep extracts the class names it references.\n\nIt then tries to resolve each class name to `BUILD` rules that provide it, by\nemploying a set of strategies (\"resolvers\") in sequence.\n\nOnce a set of possible `BUILD` rules is found, it is filtered down according to\n`visibility`, `tags` and so on.\n\nThe following subsections detail different parts of Jadep.\n\n### Detailed Flow\n\n1.  Connect to the PackageLoader server\n    ([GrpcLocalServer](https://github.com/bazelbuild/tools_jvm_autodeps/tree/master/java/com/google/devtools/javatools/jade/pkgloader))\n\n2.  Jadep parses Java files to learn which fully-qualified names (FQNs) are\n    referenced. This requires knowing which classes are defined in the same file\n    (e.g., another inner class or a template type name) which is done by\n    computing \"jump-to-definition\" information and then discarding all class\n    names not defined in the same file.\n\n    Implemented in\n    \u003chttps://github.com/bazelbuild/tools_jvm_autodeps/blob/master/lang/java/parser/parser.go\u003e\n\n3.  The FQNs are passed to a sequence of \"resolvers\". A \"resolver\" returns BUILD\n    rule candidates that can be used to satisfy a dependency on an FQN. Once a\n    resolver returns a candidate for an FQN (i.e., it resolves it), the FQN is\n    not passed on to additional resolvers. This is done to (a) improve\n    performance and (b) allow ordering resolvers by accuracy to improve its\n    quality.\n\n    The resolver interface is defined in\n    \u003chttps://github.com/bazelbuild/tools_jvm_autodeps/blob/2d9ab49baf4b1866abe0b4d670dd356ada30fbb4/jadeplib/jadeplib.go#L51\u003e\n\n    More details in the Resolver sections, below.\n\n4.  Candidates are filtered by visibility, tags, etc. Visibility sometimes\n    requires interpreting multiple BUILD files, and care was taken to interpret\n    as many as possible in parallel.\n\n    Code:\n    \u003chttps://github.com/bazelbuild/tools_jvm_autodeps/blob/master/filter/filter.go\u003e\n\n5.  Finally, Jadep asks the user which rule to add.\n\n![Flow Diagram](flow-sequence.svg)\n\n### Extracting Class Names\n\nJadep parses a Java file to obtain an AST, then partially resolves it: each\nsymbol is mapped to its place of definition. For example, a call to a method\nmaps to the method's definition.\n\nJadep then walks the AST and finds all\n\n1.  symbols that must be class names based on the Java 8 grammar\n2.  symbols that can be class names, and aren't defined anywhere in the same\n    Java file\n\nUnqualified class names are assumed to be in the same package as the Java file.\n\nThis technique gives pretty good results, but the semantics of Java make it\nimpossible to be 100% correct. For example, a subclass has access to all the\n(visible) inner classes of its superclass, without having to explicitly import\nthem. Jadep doesn't follow inheritance chains because it means reading arbitrary\nfiles, so it doesn't know which symbols are inherited.\n\n### Resolver: File System\n\nJava source files are typically organized in the file system according to their\npackage and class name, and this resolver utilizes this structure to find BUILD\nrules.\n\nIt is based on the convention that a class named `com.foo.Bar` will be\ndefined in a file named `\u003ccontent root\u003e/com/foo/Bar.java`.\n\nThe `\u003ccontent root\u003e` is by default either one of `{src/main/java,\nsrc/test/java}`.\n\nThe resolver derives a set of file names from the set of content roots and a\ntransformation of the class names it's looking for, and searches for BUILD rules\nthat have these files in their `srcs` attributes.\n\nThe resolver also handles `java_library.exports` attributes and `alias()` rules\nso long as they're in the same Bazel package as the composed file name.\n\n### Resolver: JDK / Android SDK\n\nJDK class names (e.g. `java.util.List`) do not need any BUILD dependencies to\nbuild, so this resolver simply maps these classes to nothing, ensuring that\nJadep won't add anything for them.\n\nBazel Android rules don't need dependencies for Android SDK classes, so this\nresolver also handles these classes.\n\n### Reading `BUILD` files\n\nSince Jadep interacts with existing Bazel rules (e.g., when filtering by\n`visibility`) it needs to read `BUILD` files.\n\nWe use Bazel's [Skylark\ninterpreter](https://github.com/bazelbuild/bazel/blob/0.10.0/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java) rather than [Buildozer](https://github.com/bazelbuild/buildtools/tree/c98ff0c6395f09b1942e6f7c42bf3ec15e3b9ca7/buildozer), because the latter is unable to interpret macros.\n\nSince the Skylark interpreter is written in Java, a persistent local [gRPC](https://grpc.io/) server is\nused to avoid repeatedly paying startup costs.\n\n## Extending / Hacking / Future Ideas\n\n*   The [dictresolver.go](??) is a resolver that uses a plain-text class -\u003e\n    BUILD mapping encoded in CSV, and can be used as an example for how to write\n    a performant resolver.\n*   A Maven Central resolver would be useful - it would search class names in\n    Maven Central and add their coordinates to a\n    [bazel-deps](https://github.com/johnynek/bazel-deps) configuration.\n*   [Kythe](http://kythe.io) could be used to generate an index that Jadep uses.\n\n## Bugs\n\n1.  Jadep doesn't yet handle external repositories. The `bazel.Label` data\n    structure is unaware of them, as is `GrpcLocalServer`.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgrushko%2Ftools_jvm_autodeps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcgrushko%2Ftools_jvm_autodeps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgrushko%2Ftools_jvm_autodeps/lists"}