Have all Fragment constructors take BuildOptions.

This gives us a consistent API call for creating fragments, which makes
ConfigurationFragmentFactory.create() trivial.

This clears another obstacle toward removing ConfigurationFragmentFactory.

Some constructors have been made public in support of the expected change to
eventually call them directly.

PiperOrigin-RevId: 342108784
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
index a4bc653..f95800d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfiguration.java
@@ -37,17 +37,15 @@
   private final ImmutableList<String> extraToolchains;
   private final List<Map.Entry<RegexFilter, List<Label>>> targetFilterToAdditionalExecConstraints;
 
-  PlatformConfiguration(
-      Label hostPlatform,
-      ImmutableList<String> extraExecutionPlatforms,
-      Label targetPlatform,
-      ImmutableList<String> extraToolchains,
-      List<Map.Entry<RegexFilter, List<Label>>> targetFilterToAdditionalExecConstraints) {
-    this.hostPlatform = hostPlatform;
-    this.extraExecutionPlatforms = extraExecutionPlatforms;
-    this.targetPlatform = targetPlatform;
-    this.extraToolchains = extraToolchains;
-    this.targetFilterToAdditionalExecConstraints = targetFilterToAdditionalExecConstraints;
+  public PlatformConfiguration(BuildOptions buildOptions) {
+    PlatformOptions platformOptions = buildOptions.get(PlatformOptions.class);
+
+    this.hostPlatform = platformOptions.computeHostPlatform();
+    this.extraExecutionPlatforms = ImmutableList.copyOf(platformOptions.extraExecutionPlatforms);
+    this.targetPlatform = platformOptions.computeTargetPlatform();
+    this.extraToolchains = ImmutableList.copyOf(platformOptions.extraToolchains);
+    this.targetFilterToAdditionalExecConstraints =
+        platformOptions.targetFilterToAdditionalExecConstraints;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfigurationLoader.java
index 445d643..ca061fe 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PlatformConfigurationLoader.java
@@ -14,7 +14,6 @@
 
 package com.google.devtools.build.lib.analysis;
 
-import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory;
 import com.google.devtools.build.lib.analysis.config.Fragment;
@@ -25,14 +24,7 @@
   @Override
   public PlatformConfiguration create(BuildOptions buildOptions)
       throws InvalidConfigurationException {
-    PlatformOptions platformOptions = buildOptions.get(PlatformOptions.class);
-
-    return new PlatformConfiguration(
-        platformOptions.computeHostPlatform(),
-        ImmutableList.copyOf(platformOptions.extraExecutionPlatforms),
-        platformOptions.computeTargetPlatform(),
-        ImmutableList.copyOf(platformOptions.extraToolchains),
-        platformOptions.targetFilterToAdditionalExecConstraints);
+    return new PlatformConfiguration(buildOptions);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestConfiguration.java
index 61e1813..b889399 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestConfiguration.java
@@ -301,10 +301,11 @@
     @Override
     public Fragment create(BuildOptions buildOptions)
         throws InvalidConfigurationException {
+      // TODO(gregce): Have TestConfiguration set itself to a non-functional state if this is true.
       if (!buildOptions.contains(TestOptions.class)) {
         return null;
       }
-      return new TestConfiguration(buildOptions.get(TestOptions.class));
+      return new TestConfiguration(buildOptions);
     }
 
     @Override
@@ -316,7 +317,8 @@
   private final TestOptions options;
   private final ImmutableMap<TestTimeout, Duration> testTimeout;
 
-  private TestConfiguration(TestOptions options) {
+  private TestConfiguration(BuildOptions buildOptions) {
+    TestOptions options = buildOptions.get(TestOptions.class);
     this.options = options;
     this.testTimeout = ImmutableMap.copyOf(options.testTimeout);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
index 61a5449..32c148a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
@@ -109,16 +109,7 @@
     @Override
     public Fragment create(BuildOptions buildOptions)
         throws InvalidConfigurationException {
-      BazelPythonConfiguration pythonConfiguration
-          = new BazelPythonConfiguration(buildOptions.get(Options.class));
-
-      String pythonPath = pythonConfiguration.getPythonPath();
-      if (!pythonPath.startsWith("python") && !PathFragment.create(pythonPath).isAbsolute()) {
-        throw new InvalidConfigurationException(
-            "python_path must be an absolute path when it is set.");
-      }
-
-      return pythonConfiguration;
+      return new BazelPythonConfiguration(buildOptions);
     }
 
     @Override
@@ -129,8 +120,13 @@
 
   private final Options options;
 
-  private BazelPythonConfiguration(Options options) {
-    this.options = options;
+  private BazelPythonConfiguration(BuildOptions buildOptions) throws InvalidConfigurationException {
+    this.options = buildOptions.get(Options.class);
+    String pythonPath = getPythonPath();
+    if (!pythonPath.startsWith("python") && !PathFragment.create(pythonPath).isAbsolute()) {
+      throw new InvalidConfigurationException(
+          "python_path must be an absolute path when it is set.");
+    }
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index 39a954f..e261fde 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -955,7 +955,7 @@
   public static class Loader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) throws InvalidConfigurationException {
-      return new AndroidConfiguration(buildOptions.get(Options.class));
+      return new AndroidConfiguration(buildOptions);
     }
 
     @Override
@@ -1011,7 +1011,8 @@
   private final boolean disableInstrumentationManifestMerging;
   private final boolean incompatibleUseToolchainResolution;
 
-  private AndroidConfiguration(Options options) throws InvalidConfigurationException {
+  private AndroidConfiguration(BuildOptions buildOptions) throws InvalidConfigurationException {
+    Options options = buildOptions.get(Options.class);
     this.sdk = options.sdk;
     this.cpu = options.cpu;
     this.configurationDistinguisher = options.configurationDistinguisher;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestConfiguration.java
index 1f045c6..e482434 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestConfiguration.java
@@ -53,7 +53,7 @@
     @Nullable
     @Override
     public Fragment create(BuildOptions buildOptions) {
-      return new AndroidLocalTestConfiguration(buildOptions.get(Options.class));
+      return new AndroidLocalTestConfiguration(buildOptions);
     }
 
     @Override
@@ -64,8 +64,9 @@
 
   private final boolean androidLocalTestBinaryResources;
 
-  private AndroidLocalTestConfiguration(Options options) {
-    this.androidLocalTestBinaryResources = options.androidLocalTestBinaryResources;
+  private AndroidLocalTestConfiguration(BuildOptions buildOptions) {
+    this.androidLocalTestBinaryResources =
+        buildOptions.get(Options.class).androidLocalTestBinaryResources;
   }
 
   public boolean useAndroidLocalTestBinaryResources() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index 0374924..dd44e64 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -80,7 +80,9 @@
   private final boolean mandatoryMinimumVersion;
   private final boolean objcProviderFromLinked;
 
-  private AppleConfiguration(AppleCommandLineOptions options, String iosCpu) {
+  private AppleConfiguration(BuildOptions buildOptions) {
+    AppleCommandLineOptions options = buildOptions.get(AppleCommandLineOptions.class);
+    String iosCpu = iosCpuFromCpu(buildOptions.get(CoreOptions.class).cpu);
     this.options = options;
     this.iosCpu = iosCpu;
     this.appleSplitCpu = Preconditions.checkNotNull(options.appleSplitCpu, "appleSplitCpu");
@@ -433,11 +435,6 @@
     return options.hashCode();
   }
 
-  @VisibleForTesting
-  static AppleConfiguration create(AppleCommandLineOptions appleOptions, String cpu) {
-    return new AppleConfiguration(appleOptions, iosCpuFromCpu(cpu));
-  }
-
   /**
    * Compute the platform-type-to-bitcode-mode mapping from the pairs that were passed on the
    * command line.
@@ -473,9 +470,7 @@
   public static class Loader implements ConfigurationFragmentFactory {
     @Override
     public AppleConfiguration create(BuildOptions buildOptions) {
-      AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class);
-      String cpu = buildOptions.get(CoreOptions.class).cpu;
-      return AppleConfiguration.create(appleOptions, cpu);
+      return new AppleConfiguration(buildOptions);
     }
 
     @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
index 7439803..b83a402 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/swift/SwiftConfiguration.java
@@ -32,8 +32,8 @@
 public class SwiftConfiguration extends Fragment implements SwiftConfigurationApi {
   private final ImmutableList<String> copts;
 
-  private SwiftConfiguration(SwiftCommandLineOptions options) {
-    this.copts = ImmutableList.copyOf(options.copts);
+  public SwiftConfiguration(BuildOptions buildOptions) {
+    this.copts = ImmutableList.copyOf(buildOptions.get(SwiftCommandLineOptions.class).copts);
   }
 
   @Override
@@ -52,9 +52,7 @@
     @Override
     public SwiftConfiguration create(BuildOptions buildOptions)
         throws InvalidConfigurationException {
-      SwiftCommandLineOptions options = buildOptions.get(SwiftCommandLineOptions.class);
-
-      return new SwiftConfiguration(options);
+      return new SwiftConfiguration(buildOptions);
     }
 
     @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
index 2119aab..9fb589a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlagConfiguration.java
@@ -43,7 +43,7 @@
   public static final class Loader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) throws InvalidConfigurationException {
-      return new ConfigFeatureFlagConfiguration(FeatureFlagValue.getFlagValues(buildOptions));
+      return new ConfigFeatureFlagConfiguration(buildOptions);
     }
 
     @Override
@@ -56,6 +56,11 @@
   @Nullable private final String flagHash;
 
   /** Creates a new configuration fragment from the given {@link ConfigFeatureFlagOptions}. */
+  public ConfigFeatureFlagConfiguration(BuildOptions buildOptions)
+      throws InvalidConfigurationException {
+    this(FeatureFlagValue.getFlagValues(buildOptions));
+  }
+
   @VisibleForTesting
   ConfigFeatureFlagConfiguration(ImmutableSortedMap<Label, String> flagValues) {
     this.flagValues = flagValues;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index 13c0c6b..5080ac7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -171,7 +171,7 @@
 
   private final CoreOptions.FatApkSplitSanitizer fatApkSplitSanitizer;
 
-  static CppConfiguration create(BuildOptions options) throws InvalidConfigurationException {
+  public CppConfiguration(BuildOptions options) throws InvalidConfigurationException {
     CppOptions cppOptions = options.get(CppOptions.class);
 
     CoreOptions commonOptions = options.get(CoreOptions.class);
@@ -219,64 +219,29 @@
       }
     }
 
-    return new CppConfiguration(
-        commonOptions.cpu,
-        fdoPath,
-        fdoProfileLabel,
-        csFdoAbsolutePath,
-        ImmutableList.copyOf(cppOptions.conlyoptList),
-        ImmutableList.copyOf(cppOptions.coptList),
-        ImmutableList.copyOf(cppOptions.cxxoptList),
-        linkoptsBuilder.build(),
-        ImmutableList.copyOf(cppOptions.ltoindexoptList),
-        ImmutableList.copyOf(cppOptions.ltobackendoptList),
-        cppOptions,
-        (cppOptions.stripBinaries == StripMode.ALWAYS
-            || (cppOptions.stripBinaries == StripMode.SOMETIMES
-                && compilationMode == CompilationMode.FASTBUILD)),
-        compilationMode,
-        commonOptions.collectCodeCoverage,
-        commonOptions.isHost || commonOptions.isExec,
-        (cppOptions.appleGenerateDsym
-            || (cppOptions.appleEnableAutoDsymDbg && compilationMode == CompilationMode.DBG)),
-        commonOptions.fatApkSplitSanitizer);
-  }
-
-  private CppConfiguration(
-      String cpu,
-      PathFragment fdoPath,
-      Label fdoOptimizeLabel,
-      PathFragment csFdoAbsolutePath,
-      ImmutableList<String> conlyopts,
-      ImmutableList<String> copts,
-      ImmutableList<String> cxxopts,
-      ImmutableList<String> linkopts,
-      ImmutableList<String> ltoindexOptions,
-      ImmutableList<String> ltobackendOptions,
-      CppOptions cppOptions,
-      boolean stripBinaries,
-      CompilationMode compilationMode,
-      boolean collectCodeCoverage,
-      boolean isToolConfiguration,
-      boolean appleGenerateDsym,
-      CoreOptions.FatApkSplitSanitizer fatApkSplitSanitizer) {
-    this.cpu = cpu;
+    this.cpu = commonOptions.cpu;
     this.fdoPath = fdoPath;
-    this.fdoOptimizeLabel = fdoOptimizeLabel;
+    this.fdoOptimizeLabel = fdoProfileLabel;
     this.csFdoAbsolutePath = csFdoAbsolutePath;
-    this.conlyopts = conlyopts;
-    this.copts = copts;
-    this.cxxopts = cxxopts;
-    this.linkopts = linkopts;
-    this.ltoindexOptions = ltoindexOptions;
-    this.ltobackendOptions = ltobackendOptions;
+    this.conlyopts = ImmutableList.copyOf(cppOptions.conlyoptList);
+    this.copts = ImmutableList.copyOf(cppOptions.coptList);
+    this.cxxopts = ImmutableList.copyOf(cppOptions.cxxoptList);
+    this.linkopts = linkoptsBuilder.build();
+    this.ltoindexOptions = ImmutableList.copyOf(cppOptions.ltoindexoptList);
+    this.ltobackendOptions = ImmutableList.copyOf(cppOptions.ltobackendoptList);
     this.cppOptions = cppOptions;
-    this.stripBinaries = stripBinaries;
+    this.stripBinaries =
+        cppOptions.stripBinaries == StripMode.ALWAYS
+            || (cppOptions.stripBinaries == StripMode.SOMETIMES
+                && compilationMode == CompilationMode.FASTBUILD);
     this.compilationMode = compilationMode;
-    this.collectCodeCoverage = collectCodeCoverage;
-    this.isToolConfigurationDoNotUseWillBeRemovedFor129045294 = isToolConfiguration;
-    this.appleGenerateDsym = appleGenerateDsym;
-    this.fatApkSplitSanitizer = fatApkSplitSanitizer;
+    this.collectCodeCoverage = commonOptions.collectCodeCoverage;
+    this.isToolConfigurationDoNotUseWillBeRemovedFor129045294 =
+        commonOptions.isHost || commonOptions.isExec;
+    this.appleGenerateDsym =
+        (cppOptions.appleGenerateDsym
+            || (cppOptions.appleEnableAutoDsymDbg && compilationMode == CompilationMode.DBG));
+    this.fatApkSplitSanitizer = commonOptions.fatApkSplitSanitizer;
   }
 
   /** Returns the label of the <code>cc_compiler</code> rule for the C++ configuration. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
index 7e435be..f4c6388 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
@@ -33,6 +33,6 @@
 
   @Override
   public CppConfiguration create(BuildOptions options) throws InvalidConfigurationException {
-    return CppConfiguration.create(options);
+    return new CppConfiguration(options);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQueryConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQueryConfiguration.java
index 68994c9..60a2e41 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQueryConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQueryConfiguration.java
@@ -44,8 +44,7 @@
   static class Loader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) throws InvalidConfigurationException {
-      return new GenQueryConfiguration(
-          buildOptions.get(GenQueryOptions.class).compressInMemoryResults);
+      return new GenQueryConfiguration(buildOptions);
     }
 
     @Override
@@ -56,8 +55,9 @@
 
   private final boolean inMemoryCompressionEnabled;
 
-  GenQueryConfiguration(boolean inMemoryCompressionEnabled) {
-    this.inMemoryCompressionEnabled = inMemoryCompressionEnabled;
+  public GenQueryConfiguration(BuildOptions buildOptions) {
+    this.inMemoryCompressionEnabled =
+        buildOptions.get(GenQueryOptions.class).compressInMemoryResults;
   }
 
   /** Returns whether or not genquery stored in memory can be stored in compressed form. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index d1d83cc..2972d67 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -118,7 +118,8 @@
   // TODO(dmarting): remove once we have a proper solution for #2539
   private final boolean useLegacyBazelJavaTest;
 
-  JavaConfiguration(JavaOptions javaOptions) throws InvalidConfigurationException {
+  public JavaConfiguration(BuildOptions buildOptions) throws InvalidConfigurationException {
+    JavaOptions javaOptions = buildOptions.get(JavaOptions.class);
     this.commandLineJavacFlags =
         ImmutableList.copyOf(JavaHelper.tokenizeJavaOptions(javaOptions.javacOpts));
     this.javaLauncherLabel = javaOptions.javaLauncher;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
index 40b7d75..c74461d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfigurationLoader.java
@@ -25,7 +25,7 @@
 public class JavaConfigurationLoader implements ConfigurationFragmentFactory {
   @Override
   public JavaConfiguration create(BuildOptions buildOptions) throws InvalidConfigurationException {
-    return new JavaConfiguration(buildOptions.get(JavaOptions.class));
+    return new JavaConfiguration(buildOptions);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
index 26d3d8f..24ab99b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
@@ -72,7 +72,7 @@
   public static class Loader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) {
-      return new J2ObjcConfiguration(buildOptions.get(J2ObjcCommandLineOptions.class));
+      return new J2ObjcConfiguration(buildOptions);
     }
 
     @Override
@@ -87,7 +87,8 @@
   private final boolean experimentalShorterHeaderPath;
   @Nullable private final Label deadCodeReport;
 
-  private J2ObjcConfiguration(J2ObjcCommandLineOptions j2ObjcOptions) {
+  public J2ObjcConfiguration(BuildOptions buildOptions) {
+    J2ObjcCommandLineOptions j2ObjcOptions = buildOptions.get(J2ObjcCommandLineOptions.class);
     this.translationFlags =
         ImmutableList.<String>builder()
             .addAll(J2OBJC_DEFAULT_TRANSLATION_FLAGS)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
index c5ec329..7097c06 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
@@ -17,6 +17,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.CompilationMode;
 import com.google.devtools.build.lib.analysis.config.CoreOptions;
 import com.google.devtools.build.lib.analysis.config.Fragment;
@@ -70,8 +71,11 @@
   private final boolean compileInfoMigration;
   private final boolean avoidHardcodedCompilationFlags;
 
-  ObjcConfiguration(
-      CppOptions cppOptions, ObjcCommandLineOptions objcOptions, CoreOptions options) {
+  ObjcConfiguration(BuildOptions buildOptions) {
+    CoreOptions options = buildOptions.get(CoreOptions.class);
+    CppOptions cppOptions = buildOptions.get(CppOptions.class);
+    ObjcCommandLineOptions objcOptions = buildOptions.get(ObjcCommandLineOptions.class);
+
     this.iosSimulatorDevice = objcOptions.iosSimulatorDevice;
     this.iosSimulatorVersion = DottedVersion.maybeUnwrap(objcOptions.iosSimulatorVersion);
     this.watchosSimulatorDevice = objcOptions.watchosSimulatorDevice;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
index e181a09..7bb624e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfigurationLoader.java
@@ -16,10 +16,8 @@
 
 import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory;
-import com.google.devtools.build.lib.analysis.config.CoreOptions;
 import com.google.devtools.build.lib.analysis.config.Fragment;
 import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
-import com.google.devtools.build.lib.rules.cpp.CppOptions;
 
 /**
  * A loader that creates ObjcConfiguration instances based on Objective-C configurations and
@@ -28,10 +26,7 @@
 public class ObjcConfigurationLoader implements ConfigurationFragmentFactory {
   @Override
   public ObjcConfiguration create(BuildOptions buildOptions) throws InvalidConfigurationException {
-    CoreOptions options = buildOptions.get(CoreOptions.class);
-    CppOptions cppOptions = buildOptions.get(CppOptions.class);
-    ObjcCommandLineOptions objcOptions = buildOptions.get(ObjcCommandLineOptions.class);
-    return new ObjcConfiguration(cppOptions, objcOptions, options);
+    return new ObjcConfiguration(buildOptions);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
index bc44323..ed64dc7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
@@ -200,7 +200,7 @@
     @Override
     public Fragment create(BuildOptions buildOptions)
         throws InvalidConfigurationException {
-      return new ProtoConfiguration(buildOptions.get(Options.class));
+      return new ProtoConfiguration(buildOptions);
     }
 
     @Override
@@ -214,7 +214,8 @@
   private final ImmutableList<String> ccProtoLibrarySourceSuffixes;
   private final Options options;
 
-  private ProtoConfiguration(Options options) {
+  private ProtoConfiguration(BuildOptions buildOptions) {
+    Options options = buildOptions.get(Options.class);
     this.protocOpts = ImmutableList.copyOf(options.protocOpts);
     this.ccProtoLibraryHeaderSuffixes = ImmutableList.copyOf(options.ccProtoLibraryHeaderSuffixes);
     this.ccProtoLibrarySourceSuffixes = ImmutableList.copyOf(options.ccProtoLibrarySourceSuffixes);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
index 8c70399..3734625 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java
@@ -17,6 +17,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.devtools.build.docgen.annot.DocCategory;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.Fragment;
 import com.google.devtools.build.lib.analysis.config.RequiresOptions;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -56,25 +57,19 @@
 
   private final boolean defaultToExplicitInitPy;
 
-  PythonConfiguration(
-      PythonVersion version,
-      PythonVersion defaultVersion,
-      TriState buildPythonZip,
-      boolean buildTransitiveRunfilesTrees,
-      boolean py2OutputsAreSuffixed,
-      boolean disallowLegacyPyProvider,
-      boolean useToolchains,
-      boolean loadPythonRulesFromBzl,
-      boolean defaultToExplicitInitPy) {
-    this.version = version;
-    this.defaultVersion = defaultVersion;
-    this.buildPythonZip = buildPythonZip;
-    this.buildTransitiveRunfilesTrees = buildTransitiveRunfilesTrees;
-    this.py2OutputsAreSuffixed = py2OutputsAreSuffixed;
-    this.disallowLegacyPyProvider = disallowLegacyPyProvider;
-    this.useToolchains = useToolchains;
-    this.loadPythonRulesFromBzl = loadPythonRulesFromBzl;
-    this.defaultToExplicitInitPy = defaultToExplicitInitPy;
+  public PythonConfiguration(BuildOptions buildOptions) {
+    PythonOptions pythonOptions = buildOptions.get(PythonOptions.class);
+    PythonVersion pythonVersion = pythonOptions.getPythonVersion();
+
+    this.version = pythonVersion;
+    this.defaultVersion = pythonOptions.getDefaultPythonVersion();
+    this.buildPythonZip = pythonOptions.buildPythonZip;
+    this.buildTransitiveRunfilesTrees = pythonOptions.buildTransitiveRunfilesTrees;
+    this.py2OutputsAreSuffixed = pythonOptions.incompatiblePy2OutputsAreSuffixed;
+    this.disallowLegacyPyProvider = pythonOptions.incompatibleDisallowLegacyPyProvider;
+    this.useToolchains = pythonOptions.incompatibleUsePythonToolchains;
+    this.loadPythonRulesFromBzl = pythonOptions.loadPythonRulesFromBzl;
+    this.defaultToExplicitInitPy = pythonOptions.incompatibleDefaultToExplicitInitPy;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
index e4d3a99..5cc3721 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfigurationLoader.java
@@ -25,18 +25,7 @@
   @Override
   public PythonConfiguration create(BuildOptions buildOptions)
       throws InvalidConfigurationException {
-    PythonOptions pythonOptions = buildOptions.get(PythonOptions.class);
-    PythonVersion pythonVersion = pythonOptions.getPythonVersion();
-    return new PythonConfiguration(
-        pythonVersion,
-        pythonOptions.getDefaultPythonVersion(),
-        pythonOptions.buildPythonZip,
-        pythonOptions.buildTransitiveRunfilesTrees,
-        /*py2OutputsAreSuffixed=*/ pythonOptions.incompatiblePy2OutputsAreSuffixed,
-        /*disallowLegacyPyProvider=*/ pythonOptions.incompatibleDisallowLegacyPyProvider,
-        /*useToolchains=*/ pythonOptions.incompatibleUsePythonToolchains,
-        /*loadPythonRulesFromBzl=*/ pythonOptions.loadPythonRulesFromBzl,
-        /*defaultToExplicitInitPy=*/ pythonOptions.incompatibleDefaultToExplicitInitPy);
+    return new PythonConfiguration(buildOptions);
   }
 
   @Override
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisCachingTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisCachingTest.java
index a18dd96..d1a6e45 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisCachingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisCachingTest.java
@@ -612,12 +612,14 @@
 
   @StarlarkBuiltin(name = "test_diff_fragment", doc = "fragment for testing differy fragments")
   @RequiresOptions(options = {DiffResetOptions.class})
-  private static final class DiffResetFragment extends Fragment implements StarlarkValue {}
+  private static final class DiffResetFragment extends Fragment implements StarlarkValue {
+    public DiffResetFragment(BuildOptions buildOptions) {}
+  }
 
   private static final class DiffResetFactory implements ConfigurationFragmentFactory {
     @Override
-    public Fragment create(BuildOptions options) {
-      return new DiffResetFragment();
+    public Fragment create(BuildOptions buildOptions) {
+      return new DiffResetFragment(buildOptions);
     }
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LateBoundSplitUtil.java b/src/test/java/com/google/devtools/build/lib/analysis/LateBoundSplitUtil.java
index 6c518cf..4b03e5e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/LateBoundSplitUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/LateBoundSplitUtil.java
@@ -46,7 +46,17 @@
   /** The {@link Fragment} that contains the options. */
   @AutoCodec
   @RequiresOptions(options = {TestOptions.class})
-  static class TestFragment extends Fragment {}
+  static class TestFragment extends Fragment {
+    private final BuildOptions buildOptions;
+
+    public TestFragment(BuildOptions buildOptions) {
+      this.buildOptions = buildOptions;
+    }
+    // Getter required to satisfy AutoCodec.
+    public BuildOptions getBuildOptions() {
+      return buildOptions;
+    }
+  }
 
   /**
    * The fragment's loader.
@@ -54,7 +64,7 @@
   static class FragmentLoader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) {
-      return new TestFragment();
+      return new TestFragment(buildOptions);
     }
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
index 38b553b..1e5471d 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
@@ -47,7 +47,9 @@
    * A fragment containing flags that exhibit different flag behaviors for easy testing purposes.
    */
   @RequiresOptions(options = {DummyTestOptions.class})
-  private static class DummyTestFragment extends Fragment {}
+  private static class DummyTestFragment extends Fragment {
+    public DummyTestFragment(BuildOptions buildOptions) {}
+  }
 
   /** Flags that exhibit an variety of flag behaviors. */
   public static class DummyTestOptions extends FragmentOptions {
@@ -90,7 +92,7 @@
 
     @Override
     public Fragment create(BuildOptions buildOptions) throws InvalidConfigurationException {
-      return new DummyTestFragment();
+      return new DummyTestFragment(buildOptions);
     }
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/rules/LateBoundAliasTest.java b/src/test/java/com/google/devtools/build/lib/rules/LateBoundAliasTest.java
index 4316a60..6aafc4c 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/LateBoundAliasTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/LateBoundAliasTest.java
@@ -39,7 +39,9 @@
 @RunWith(JUnit4.class)
 public class LateBoundAliasTest extends BuildViewTestCase {
 
-  private static final class TestFragment extends Fragment {}
+  private static final class TestFragment extends Fragment {
+    public TestFragment(BuildOptions buildOptions) {}
+  }
 
   private static final class TestFragmentOptionFactory implements ConfigurationFragmentFactory {
 
@@ -51,7 +53,7 @@
     @Nullable
     @Override
     public Fragment create(BuildOptions buildOptions) {
-      return new TestFragment();
+      return new TestFragment(buildOptions);
     }
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
index d130484..21468bd 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
@@ -111,12 +111,22 @@
 
   @AutoCodec
   @RequiresOptions(options = {DummyTestOptions.class})
-  static class DummyTestOptionsFragment extends Fragment {}
+  static class DummyTestOptionsFragment extends Fragment {
+    private final BuildOptions buildOptions;
+
+    public DummyTestOptionsFragment(BuildOptions buildOptions) {
+      this.buildOptions = buildOptions;
+    }
+    // Getter required to satisfy AutoCodec.
+    public BuildOptions getBuildOptions() {
+      return buildOptions;
+    }
+  }
 
   private static class DummyTestOptionsLoader implements ConfigurationFragmentFactory {
     @Override
     public Fragment create(BuildOptions buildOptions) {
-      return new DummyTestOptionsFragment();
+      return new DummyTestOptionsFragment(buildOptions);
     }
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/trimming/TrimmableTestConfigurationFragments.java b/src/test/java/com/google/devtools/build/lib/skyframe/trimming/TrimmableTestConfigurationFragments.java
index 1dfd658..dbe1168 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/trimming/TrimmableTestConfigurationFragments.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/trimming/TrimmableTestConfigurationFragments.java
@@ -440,13 +440,12 @@
   @RequiresOptions(options = {AOptions.class})
   public static final class AConfig extends Fragment implements StarlarkValue {
     public static final ConfigurationFragmentFactory FACTORY =
-        new FragmentLoader<>(
-            AConfig.class, (options) -> new AConfig(options.get(AOptions.class).alpha));
+        new FragmentLoader<>(AConfig.class, AConfig::new);
 
     private final String value;
 
-    public AConfig(String value) {
-      this.value = value;
+    public AConfig(BuildOptions buildOptions) {
+      this.value = buildOptions.get(AOptions.class).alpha;
     }
 
     @Override
@@ -470,13 +469,12 @@
   @RequiresOptions(options = {BOptions.class})
   public static final class BConfig extends Fragment implements StarlarkValue {
     public static final ConfigurationFragmentFactory FACTORY =
-        new FragmentLoader<>(
-            BConfig.class, (options) -> new BConfig(options.get(BOptions.class).bravo));
+        new FragmentLoader<>(BConfig.class, BConfig::new);
 
     private final String value;
 
-    public BConfig(String value) {
-      this.value = value;
+    public BConfig(BuildOptions buildOptions) {
+      this.value = buildOptions.get(BOptions.class).bravo;
     }
 
     @Override
@@ -500,13 +498,12 @@
   @RequiresOptions(options = {COptions.class})
   public static final class CConfig extends Fragment implements StarlarkValue {
     public static final ConfigurationFragmentFactory FACTORY =
-        new FragmentLoader<>(
-            CConfig.class, (options) -> new CConfig(options.get(COptions.class).charlie));
+        new FragmentLoader<>(CConfig.class, CConfig::new);
 
     private final String value;
 
-    public CConfig(String value) {
-      this.value = value;
+    public CConfig(BuildOptions buildOptions) {
+      this.value = buildOptions.get(COptions.class).charlie;
     }
 
     @Override
@@ -530,13 +527,12 @@
   @RequiresOptions(options = {DOptions.class})
   public static final class DConfig extends Fragment implements StarlarkValue {
     public static final ConfigurationFragmentFactory FACTORY =
-        new FragmentLoader<>(
-            DConfig.class, (options) -> new DConfig(options.get(DOptions.class).delta));
+        new FragmentLoader<>(DConfig.class, DConfig::new);
 
     private final String value;
 
-    public DConfig(String value) {
-      this.value = value;
+    public DConfig(BuildOptions buildOptions) {
+      this.value = buildOptions.get(DOptions.class).delta;
     }
 
     @Override
@@ -563,13 +559,12 @@
   @RequiresOptions(options = {EOptions.class})
   public static final class EConfig extends Fragment implements StarlarkValue {
     public static final ConfigurationFragmentFactory FACTORY =
-        new FragmentLoader<>(
-            EConfig.class, (options) -> new EConfig(options.get(EOptions.class).echo));
+        new FragmentLoader<>(EConfig.class, EConfig::new);
 
     private final String value;
 
-    public EConfig(String value) {
-      this.value = value;
+    public EConfig(BuildOptions buildOptions) {
+      this.value = buildOptions.get(EOptions.class).echo;
     }
 
     @Override