From be119a2d96ae6f8953c2c184ba267946dffe4e63 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Tue, 8 Nov 2022 22:17:46 +0100 Subject: [PATCH] Improve documentation --- tools/java/runfiles/Runfiles.java | 121 +++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 35 deletions(-) diff --git a/tools/java/runfiles/Runfiles.java b/tools/java/runfiles/Runfiles.java index 40edb48bbe442d..464f4a2980e1f2 100644 --- a/tools/java/runfiles/Runfiles.java +++ b/tools/java/runfiles/Runfiles.java @@ -42,31 +42,64 @@ * ) * * - *

2. Import the runfiles library and the {@code AutoBazelRepository} annotation. + *

2. Import the runfiles library. * *

- *   import com.google.devtools.build.runfiles.AutoBazelRepository;
  *   import com.google.devtools.build.runfiles.Runfiles;
  * 
* - *

3. Annotate the class in which a {@code Runfiles} object is created with - * {@link AutoBazelRepository}: + *

3. Create a {@link Preloaded} object: + * + *

+ *   public void myFunction() {
+ *     Runfiles.Preloaded runfiles = Runfiles.preload();
+ *     ...
+ * 
+ * + *

4. To look up a runfile, use either of the following approaches: + * + *

4a. Annotate the class from which runfiles should be looked up with + * {@link AutoBazelRepository} and obtain the name of the Bazel repository containing the class from + * a constant generated by this annotation: * *

+ *   import com.google.devtools.build.runfiles.AutoBazelRepository;
  *   @AutoBazelRepository
  *   public class MyClass {
- *     ...
+ *     public void myFunction() {
+ *       Runfiles.Preloaded runfiles = Runfiles.preload();
+ *       String path = runfiles.withSourceRepository(AutoBazelRepository_MyClass.NAME)
+ *                             .rlocation("my_workspace/path/to/my/data.txt");
+ *       ...
+ *
  * 
* - *

4. Create a Runfiles object and use rlocation to look up runfile paths: + *

4b. Let Bazel compute the path passed to rlocation and pass it into a java_binary + * via an argument or an environment variable: * *

- *   public void myFunction() {
- *     Runfiles runfiles = Runfiles.create(AutoBazelRepository_MyClass.BAZEL_REPOSITORY);
- *     String path = runfiles.rlocation("my_workspace/path/to/my/data.txt");
- *     ...
+ *   java_binary(
+ *       name = "my_binary",
+ *       srcs = ["MyClass.java"],
+ *       data = ["@my_workspace//path/to/my:data.txt"],
+ *       env = {"MY_RUNFILE": "$(rlocationpath @my_workspace//path/to/my:data.txt)"},
+ *   )
  * 
* + *
+ *   public class MyClass {
+ *     public void myFunction() {
+ *       Runfiles.Preloaded runfiles = Runfiles.preload();
+ *       String path = runfiles.unmapped().rlocation(System.getenv("MY_RUNFILE"));
+ *       ...
+ *
+ * 
+ * + * For more details on why it is required to pass in the current repository name, see + * {@see https://bazel.build/build/bzlmod#repository-names}. + * + *

Subprocesses

+ * *

If you want to start subprocesses that also need runfiles, you need to set the right * environment variables for them: * @@ -77,9 +110,31 @@ * ... * Process p = pb.start(); * + * + *

{@link Preloaded} vs. {@link Runfiles}

+ * + *

Instances of {@link Preloaded} are meant to be stored and passed around to other components + * that need to access runfiles. They are created by calling {@link Runfiles#preload()} + * {@link Runfiles#preload(Map)} and immutably encapsulate all data required to look up runfiles + * with the repository mapping of any Bazel repository specified at a later time. + * + *

Creating {@link Runfiles} instances can be costly, so applications should try to create as few + * instances as possible. + * + *

Instance of {@link Runfiles} are only meant to be used by code located in a single Bazel + * repository and should not be passed around. They are created by calling + * {@link Preloaded#withSourceRepository(String)} or {@link Preloaded#unmapped()} and in addition to + * the data in {@link Preloaded} also fix a source repository relative to which apparent repository + * names are resolved. + * + *

Creating {@link Preloaded} instances is cheap. */ public final class Runfiles { + /** + * A class that encapsulates all data required to look up runfiles relative to any Bazel + * repository fixed at a later time. + */ public abstract static class Preloaded { /** @@ -115,24 +170,30 @@ public int hashCode() { } /** - * Returns a new instance that uses the provided source repository as a default for all calls to - * {@link #rlocation(String)}. + * Returns a {@link Runfiles} instance that uses the provided source repository's repository + * mapping to translate apparent into canonical repository names. * - *

This is useful when receiving a {@link Runfiles} instance from a different Bazel - * repository. In this case, while the runfiles manifest or directory encoded in the instance - * should be used for runfiles lookups, the repository from which apparent repository names - * should be resolved needs to change. + *

{@see https://bazel.build/build/bzlmod#repository-names} * * @param sourceRepository the canonical name of the Bazel repository relative to which apparent - * repository names should be resolved - * @return a new {@link Runfiles} instance identical to this one, except that calls to - * {@link #rlocation(String)} use the provided source repository. + * repository names should be resolved. Should generally coincide with + * the Bazel repository that contains the caller of this method, which + * can be obtained via {@link AutoBazelRepository}. + * @return a {@link Runfiles} instance that looks up runfiles relative to the provided source + * repository and shares all other data with this {@link Preloaded} instance. */ public final Runfiles withSourceRepository(String sourceRepository) { Util.checkArgument(sourceRepository != null); return new Runfiles(this, sourceRepository); } + /** + * Returns a {@link Runfiles} instance backed by the preloaded runfiles data that can be used to + * look up runfiles paths with canonical repository names only. + * + * @return a {@link Runfiles} instance that can only look up paths with canonical repository + * names and shared all data with this {@link Preloaded} instance. + */ public final Runfiles unmapped() { return new Runfiles(this, null); } @@ -159,20 +220,16 @@ private Runfiles(Preloaded preloadedRunfiles, String sourceRepository) { } /** - * Returns a new {@link Runfiles} instance. + * Returns a new {@link Runfiles.Preloaded} instance. * *

This method passes the JVM's environment variable map to {@link #create(Map)}. - * - * @param sourceRepository the canonical name of the Bazel repository relative to which runfiles - * lookups should be performed. This can be obtained using - * {@link AutoBazelRepository} (see class documentation). */ public static Preloaded preload() throws IOException { return preload(System.getenv()); } /** - * Returns a new {@link Runfiles} instance. + * Returns a new {@link Runfiles.Preloaded} instance. * *

The returned object is either: * @@ -192,10 +249,6 @@ public static Preloaded preload() throws IOException { *

Note about performance: the manifest-based implementation eagerly reads and caches the whole * manifest file upon instantiation. * - * @param sourceRepository the canonical name of the Bazel repository relative to which apparent - * repository names in runfiles paths should be resolved. This can be - * obtained using {@link AutoBazelRepository} (see class documentation). - * * @throws IOException if RUNFILES_MANIFEST_ONLY=1 is in {@code env} but there's no * "RUNFILES_MANIFEST_FILE", "RUNFILES_DIR", or "JAVA_RUNFILES" key in * {@code env} or their values are empty, or some IO error occurs @@ -214,9 +267,8 @@ public static Preloaded preload(Map env) throws IOException { /** * Returns a new {@link Runfiles} instance. * - *

Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles - * correctly if called from the main repository. Use {@link #preload()}} - * instead. + *

Deprecated: Use {@link #preload()} instead. With {@code --enable_bzlmod}, this + * function does not work correctly. * *

This method passes the JVM's environment variable map to {@link #create(Map)}. */ @@ -228,9 +280,8 @@ public static Runfiles create() throws IOException { /** * Returns a new {@link Runfiles} instance. * - *

Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles - * correctly if called from the main repository. Use {@link #preload(Map)} instead. - * + *

Deprecated: Use {@link #preload(Map)} )} instead. With {@code --enable_bzlmod}, this + * function does not work correctly. * *

The returned object is either: *