Skip to content

Commit

Permalink
Improve documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
fmeum committed Nov 10, 2022
1 parent ad33bfb commit 9ad29b6
Showing 1 changed file with 86 additions and 35 deletions.
121 changes: 86 additions & 35 deletions tools/java/runfiles/Runfiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,64 @@
* )
* </pre>
*
* <p>2. Import the runfiles library and the {@code AutoBazelRepository} annotation.
* <p>2. Import the runfiles library.
*
* <pre>
* import com.google.devtools.build.runfiles.AutoBazelRepository;
* import com.google.devtools.build.runfiles.Runfiles;
* </pre>
*
* <p>3. Annotate the class in which a {@code Runfiles} object is created with
* {@link AutoBazelRepository}:
* <p>3. Create a {@link Preloaded} object:
*
* <pre>
* public void myFunction() {
* Runfiles.Preloaded runfiles = Runfiles.preload();
* ...
* </pre>
*
* <p>4. To look up a runfile, use either of the following approaches:
*
* <p>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:
*
* <pre>
* import com.google.devtools.build.runfiles.AutoBazelRepository;
* &#64;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");
* ...
*
* </pre>
*
* <p>4. Create a Runfiles object and use rlocation to look up runfile paths:
* <p>4b. Let Bazel compute the path passed to rlocation and pass it into a <code>java_binary</code>
* via an argument or an environment variable:
*
* <pre>
* 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)"},
* )
* </pre>
*
* <pre>
* public class MyClass {
* public void myFunction() {
* Runfiles.Preloaded runfiles = Runfiles.preload();
* String path = runfiles.unmapped().rlocation(System.getenv("MY_RUNFILE"));
* ...
*
* </pre>
*
* For more details on why it is required to pass in the current repository name, see
* {@see https://bazel.build/build/bzlmod#repository-names}.
*
* <h3>Subprocesses</h3>
*
* <p>If you want to start subprocesses that also need runfiles, you need to set the right
* environment variables for them:
*
Expand All @@ -77,9 +110,31 @@
* ...
* Process p = pb.start();
* </pre>
*
* <h3>{@link Preloaded} vs. {@link Runfiles}</h3>
*
* <p>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.
*
* <p>Creating {@link Runfiles} instances can be costly, so applications should try to create as few
* instances as possible.
*
* <p>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.
*
* <p>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 {

/**
Expand Down Expand Up @@ -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.
*
* <p>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.
* <p>{@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);
}
Expand All @@ -159,20 +220,16 @@ private Runfiles(Preloaded preloadedRunfiles, String sourceRepository) {
}

/**
* Returns a new {@link Runfiles} instance.
* Returns a new {@link Runfiles.Preloaded} instance.
*
* <p>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.
*
* <p>The returned object is either:
*
Expand All @@ -192,10 +249,6 @@ public static Preloaded preload() throws IOException {
* <p>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
Expand All @@ -214,9 +267,8 @@ public static Preloaded preload(Map<String, String> env) throws IOException {
/**
* Returns a new {@link Runfiles} instance.
*
* <p><strong>Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles
* correctly if called from the main repository. Use {@link #preload()}}
* instead.</strong>
* <p><strong>Deprecated: Use {@link #preload()} instead. With {@code --enable_bzlmod}, this
* function does not work correctly.</strong>
*
* <p>This method passes the JVM's environment variable map to {@link #create(Map)}.
*/
Expand All @@ -228,9 +280,8 @@ public static Runfiles create() throws IOException {
/**
* Returns a new {@link Runfiles} instance.
*
* <p><strong>Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles
* correctly if called from the main repository. Use {@link #preload(Map)} instead.
* </strong>
* <p><strong>Deprecated: Use {@link #preload(Map)} )} instead. With {@code --enable_bzlmod}, this
* function does not work correctly.</strong>
*
* <p>The returned object is either:
*
Expand Down

0 comments on commit 9ad29b6

Please sign in to comment.