diff options
author | 2016-10-17 07:14:03 +0000 | |
---|---|---|
committer | 2016-10-17 11:19:39 +0000 | |
commit | af39f307896cf6f3015c02e312e8218557484af4 (patch) | |
tree | 943163fc8d1e08b64198f0924e72fea5af3f3c47 | |
parent | 88cf8e380d3cc3333e7903d4d67987dcc195c968 (diff) |
Split up BazelRuleClassProvider into per-language modules.
Add a test to ensure each module is internally consistent / correctly declares
its dependencies.
This enforces a certain amount of rule set modularity, and may allow us to
move the rule modules to the rule packages in the future, which would very
much clean up the RuleClassProvider (which currently depends on everything and
the kitchen sink).
--
MOS_MIGRATED_REVID=136321762
4 files changed, 525 insertions, 258 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 84efaaa308..4f0fb22867 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -16,10 +16,11 @@ package com.google.devtools.build.lib.bazel.rules; import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Functions; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; +import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.Builder; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.DeprecationValidator; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.PrerequisiteValidator; import com.google.devtools.build.lib.analysis.ConfiguredTarget; @@ -158,8 +159,18 @@ public class BazelRuleClassProvider { public static final String TOOLS_REPOSITORY = "@bazel_tools"; /** - * Used by the build encyclopedia generator. + * A coherent set of options, fragments, aspects and rules; each of these may declare a dependency + * on other such sets. */ + public static interface RuleModule { + /** Add stuff to the configured rule class provider builder. */ + void init(ConfiguredRuleClassProvider.Builder builder); + + /** List of required modules. */ + ImmutableList<RuleModule> requires(); + } + + /** Used by the build encyclopedia generator. */ public static ConfiguredRuleClassProvider create() { ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder(); @@ -224,265 +235,390 @@ public class BazelRuleClassProvider { } public static void setup(ConfiguredRuleClassProvider.Builder builder) { - initMinimal(builder); - initCpp(builder); - initJava(builder); - initAndroid(builder); - initEverythingElse(builder); + MINIMAL_RULES.init(builder); + PROTO_RULES.init(builder); + SH_RULES.init(builder); + CPP_RULES.init(builder); + JAVA_RULES.init(builder); + JAVA_PROTO_RULES.init(builder); + ANDROID_RULES.init(builder); + PYTHON_RULES.init(builder); + OBJC_RULES.init(builder); + ANDROID_STUDIO_ASPECT.init(builder); + VARIOUS_WORKSPACE_RULES.init(builder); } - @VisibleForTesting - public static void initMinimal(ConfiguredRuleClassProvider.Builder builder) { - builder - .setConfigurationCollectionFactory(new BazelConfigurationCollection()) - .setPrelude("//tools/build_rules:prelude_bazel") - .setRunfilesPrefix(Label.DEFAULT_REPOSITORY_DIRECTORY) - .setPrerequisiteValidator(new BazelPrerequisiteValidator()); - - builder.setUniversalConfigurationFragment(BazelConfiguration.class); - builder.addConfigurationOptions(BuildConfiguration.Options.class); - builder.addConfigurationOptions(ProtoConfiguration.Options.class); - builder.addConfigurationFragment(new BazelConfiguration.Loader()); - builder.addConfigurationFragment(new ProtoConfiguration.Loader()); - - builder.addRuleDefinition(new BaseRuleClasses.BaseRule()); - builder.addRuleDefinition(new BaseRuleClasses.RuleBase()); - builder.addRuleDefinition(new BaseRuleClasses.BinaryBaseRule()); - builder.addRuleDefinition(new BaseRuleClasses.TestBaseRule()); - builder.addRuleDefinition(new BaseRuleClasses.ErrorRule()); - - builder.addRuleDefinition(new EnvironmentRule()); - - builder.addRuleDefinition(new ConfigRuleClasses.ConfigBaseRule()); - builder.addRuleDefinition(new ConfigRuleClasses.ConfigSettingRule()); - - builder.addRuleDefinition(new AliasRule()); - builder.addRuleDefinition(new BazelFilegroupRule()); - builder.addRuleDefinition(new BazelTestSuiteRule()); - builder.addRuleDefinition(new BazelGenRuleRule()); - builder.addRuleDefinition(new GenQueryRule()); - - builder.addRuleDefinition(new BindRule()); - builder.addRuleDefinition(new WorkspaceBaseRule()); - builder.addRuleDefinition(new LocalRepositoryRule()); - - try { - builder.addWorkspaceFilePrefix( - ResourceFileLoader.loadResource(BazelRuleClassProvider.class, "tools.WORKSPACE")); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } + public static final RuleModule MINIMAL_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder + .setConfigurationCollectionFactory(new BazelConfigurationCollection()) + .setPrelude("//tools/build_rules:prelude_bazel") + .setRunfilesPrefix(Label.DEFAULT_REPOSITORY_DIRECTORY) + .setPrerequisiteValidator(new BazelPrerequisiteValidator()); + + builder.setUniversalConfigurationFragment(BazelConfiguration.class); + builder.addConfigurationOptions(BuildConfiguration.Options.class); + builder.addConfigurationFragment(new BazelConfiguration.Loader()); + + builder.addRuleDefinition(new BaseRuleClasses.BaseRule()); + builder.addRuleDefinition(new BaseRuleClasses.RuleBase()); + builder.addRuleDefinition(new BaseRuleClasses.BinaryBaseRule()); + builder.addRuleDefinition(new BaseRuleClasses.TestBaseRule()); + builder.addRuleDefinition(new BaseRuleClasses.ErrorRule()); + + builder.addRuleDefinition(new EnvironmentRule()); + + builder.addRuleDefinition(new ConfigRuleClasses.ConfigBaseRule()); + builder.addRuleDefinition(new ConfigRuleClasses.ConfigSettingRule()); + + builder.addRuleDefinition(new AliasRule()); + builder.addRuleDefinition(new BazelFilegroupRule()); + builder.addRuleDefinition(new BazelTestSuiteRule()); + builder.addRuleDefinition(new BazelGenRuleRule()); + builder.addRuleDefinition(new GenQueryRule()); + + builder.addRuleDefinition(new BindRule()); + builder.addRuleDefinition(new WorkspaceBaseRule()); + builder.addRuleDefinition(new LocalRepositoryRule()); + + try { + builder.addWorkspaceFilePrefix( + ResourceFileLoader.loadResource(BazelRuleClassProvider.class, "tools.WORKSPACE")); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } - @VisibleForTesting - public static void initCpp(ConfiguredRuleClassProvider.Builder builder) { - builder.addConfigurationOptions(CppOptions.class); - - builder.addBuildInfoFactory(new CppBuildInfo()); - - builder.addRuleDefinition(new CcToolchainRule()); - builder.addRuleDefinition(new CcToolchainSuiteRule()); - builder.addRuleDefinition(new CcIncLibraryRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcLinkingRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcDeclRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcBaseRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryBaseRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcTestRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryBaseRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryRule()); - builder.addRuleDefinition(new BazelCppRuleClasses.BazelCcIncLibraryRule()); - - builder.addConfigurationFragment(new CppConfigurationLoader(Functions.<String>identity())); - } + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(); + } + }; + + public static final RuleModule PROTO_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder.addConfigurationOptions(ProtoConfiguration.Options.class); + builder.addConfigurationFragment(new ProtoConfiguration.Loader()); + builder.addRuleDefinition(new BazelProtoLibraryRule()); + } - private static void initJava(ConfiguredRuleClassProvider.Builder builder) { - builder.addConfigurationOptions(JavaOptions.class); - builder.addConfigurationFragment(new JvmConfigurationLoader()); - builder.addConfigurationFragment(new JavaConfigurationLoader()); - - builder.addBuildInfoFactory(new BazelJavaBuildInfoFactory()); - - builder.addRuleDefinition(new BazelJavaRuleClasses.BaseJavaBinaryRule()); - builder.addRuleDefinition(new BazelJavaRuleClasses.IjarBaseRule()); - builder.addRuleDefinition(new BazelJavaRuleClasses.JavaBaseRule()); - builder.addRuleDefinition(new ProguardLibraryRule()); - builder.addRuleDefinition(new JavaImportBaseRule()); - builder.addRuleDefinition(new BazelJavaRuleClasses.JavaRule()); - builder.addRuleDefinition(new BazelJavaBinaryRule()); - builder.addRuleDefinition(new BazelJavaLibraryRule()); - builder.addRuleDefinition(new BazelJavaImportRule()); - builder.addRuleDefinition(new BazelJavaTestRule()); - builder.addRuleDefinition(new BazelJavaPluginRule()); - builder.addRuleDefinition(new JavaToolchainRule()); - - builder.addRuleDefinition(new BazelExtraActionRule()); - builder.addRuleDefinition(new BazelActionListenerRule()); - - try { - builder.addWorkspaceFilePrefix( - ResourceFileLoader.loadResource(BazelJavaRuleClasses.class, "jdk.WORKSPACE")); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES); + } + }; + + public static final RuleModule SH_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder.addRuleDefinition(new BazelShRuleClasses.ShRule()); + builder.addRuleDefinition(new BazelShLibraryRule()); + builder.addRuleDefinition(new BazelShBinaryRule()); + builder.addRuleDefinition(new BazelShTestRule()); + } - private static void initAndroid(ConfiguredRuleClassProvider.Builder builder) { - // The tools repository prefix must be set before calling this method. - String toolsRepository = checkNotNull(builder.getToolsRepository()); - - builder.addConfigurationOptions(AndroidConfiguration.Options.class); - builder.addConfigurationFragment(new AndroidConfiguration.Loader()); - - AndroidNeverlinkAspect androidNeverlinkAspect = new AndroidNeverlinkAspect(); - DexArchiveAspect dexArchiveAspect = new DexArchiveAspect(toolsRepository); - JackAspect jackAspect = new JackAspect(toolsRepository); - builder.addNativeAspectClass(androidNeverlinkAspect); - builder.addNativeAspectClass(dexArchiveAspect); - builder.addNativeAspectClass(jackAspect); - - builder.addRuleDefinition(new AndroidRuleClasses.AndroidSdkRule()); - builder.addRuleDefinition(new BazelAndroidToolsDefaultsJarRule()); - builder.addRuleDefinition(new AndroidRuleClasses.AndroidBaseRule()); - builder.addRuleDefinition(new AndroidRuleClasses.AndroidAaptBaseRule()); - builder.addRuleDefinition(new AndroidRuleClasses.AndroidResourceSupportRule()); - builder.addRuleDefinition(new AndroidRuleClasses.AndroidBinaryBaseRule( - androidNeverlinkAspect, dexArchiveAspect, jackAspect)); - builder.addRuleDefinition(new AndroidBinaryOnlyRule()); - builder.addRuleDefinition(new AndroidLibraryBaseRule(androidNeverlinkAspect, jackAspect)); - builder.addRuleDefinition(new BazelAndroidLibraryRule()); - builder.addRuleDefinition(new BazelAndroidBinaryRule()); - builder.addRuleDefinition(new AarImportBaseRule()); - builder.addRuleDefinition(new BazelAarImportRule()); - - builder.addSkylarkAccessibleTopLevels("android_common", new AndroidSkylarkCommon()); - - try { - builder.addWorkspaceFilePrefix( - ResourceFileLoader.loadResource(BazelAndroidSemantics.class, "android.WORKSPACE")); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES); + } + }; + + public static final RuleModule CPP_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder.addConfigurationOptions(CppOptions.class); + + builder.addBuildInfoFactory(new CppBuildInfo()); + + builder.addRuleDefinition(new CcToolchainRule()); + builder.addRuleDefinition(new CcToolchainSuiteRule()); + builder.addRuleDefinition(new CcIncLibraryRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcLinkingRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcDeclRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcBaseRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryBaseRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcBinaryRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcTestRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryBaseRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.CcLibraryRule()); + builder.addRuleDefinition(new BazelCppRuleClasses.BazelCcIncLibraryRule()); + + builder.addConfigurationFragment( + new CppConfigurationLoader(Functions.<String>identity())); + } - private static void initEverythingElse(ConfiguredRuleClassProvider.Builder builder) { - // The tools repository prefix must be set before calling this method. - String toolsRepository = checkNotNull(builder.getToolsRepository()); - - builder.addBuildInfoFactory(new ObjcBuildInfoFactory()); - builder.registerSkylarkProvider(ObjcProvider.OBJC_SKYLARK_PROVIDER_NAME, ObjcProvider.class); - - builder.addConfigurationOptions(PythonOptions.class); - builder.addConfigurationOptions(BazelPythonConfiguration.Options.class); - builder.addConfigurationOptions(ObjcCommandLineOptions.class); - builder.addConfigurationOptions(J2ObjcCommandLineOptions.class); - - BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect = new BazelJ2ObjcProtoAspect(toolsRepository); - J2ObjcAspect j2ObjcAspect = new J2ObjcAspect(toolsRepository, bazelJ2ObjcProtoAspect); - AndroidStudioInfoAspect androidStudioInfoAspect = - new AndroidStudioInfoAspect(toolsRepository, new BazelAndroidStudioInfoSemantics()); - ObjcProtoAspect objcProtoAspect = new ObjcProtoAspect(); - BazelJavaProtoAspect bazelJavaProtoAspect = new BazelJavaProtoAspect(); - BazelJavaLiteProtoAspect bazelJavaLiteProtoAspect = new BazelJavaLiteProtoAspect(); - - builder.addNativeAspectClass(bazelJ2ObjcProtoAspect); - builder.addNativeAspectClass(j2ObjcAspect); - builder.addNativeAspectClass(androidStudioInfoAspect); - builder.addNativeAspectClass(objcProtoAspect); - builder.addNativeAspectClass(bazelJavaProtoAspect); - builder.addNativeAspectClass(bazelJavaLiteProtoAspect); - - builder.addRuleDefinition(new BazelShRuleClasses.ShRule()); - builder.addRuleDefinition(new BazelShLibraryRule()); - builder.addRuleDefinition(new BazelShBinaryRule()); - builder.addRuleDefinition(new BazelShTestRule()); - - builder.addRuleDefinition(new BazelProtoLibraryRule()); - - builder.addRuleDefinition(new BazelPyRuleClasses.PyBaseRule()); - builder.addRuleDefinition(new BazelPyRuleClasses.PyBinaryBaseRule()); - builder.addRuleDefinition(new BazelPyLibraryRule()); - builder.addRuleDefinition(new BazelPyBinaryRule()); - builder.addRuleDefinition(new BazelPyTestRule()); - - try { - builder.addWorkspaceFilePrefix( - ResourceFileLoader.loadResource(BazelJ2ObjcLibraryRule.class, "j2objc.WORKSPACE")); - } catch (IOException e) { - throw new IllegalStateException(e); - } + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES); + } + }; + + public static final RuleModule JAVA_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder.addConfigurationOptions(JavaOptions.class); + builder.addConfigurationFragment(new JvmConfigurationLoader()); + builder.addConfigurationFragment(new JavaConfigurationLoader()); + + builder.addBuildInfoFactory(new BazelJavaBuildInfoFactory()); + + builder.addRuleDefinition(new BazelJavaRuleClasses.BaseJavaBinaryRule()); + builder.addRuleDefinition(new BazelJavaRuleClasses.IjarBaseRule()); + builder.addRuleDefinition(new BazelJavaRuleClasses.JavaBaseRule()); + builder.addRuleDefinition(new ProguardLibraryRule()); + builder.addRuleDefinition(new JavaImportBaseRule()); + builder.addRuleDefinition(new BazelJavaRuleClasses.JavaRule()); + builder.addRuleDefinition(new BazelJavaBinaryRule()); + builder.addRuleDefinition(new BazelJavaLibraryRule()); + builder.addRuleDefinition(new BazelJavaImportRule()); + builder.addRuleDefinition(new BazelJavaTestRule()); + builder.addRuleDefinition(new BazelJavaPluginRule()); + builder.addRuleDefinition(new JavaToolchainRule()); + + builder.addRuleDefinition(new BazelExtraActionRule()); + builder.addRuleDefinition(new BazelActionListenerRule()); + + try { + builder.addWorkspaceFilePrefix( + ResourceFileLoader.loadResource(BazelJavaRuleClasses.class, "jdk.WORKSPACE")); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } - builder.addRuleDefinition(new AppleCcToolchainRule()); - builder.addRuleDefinition(new AppleToolchain.RequiresXcodeConfigRule(toolsRepository)); - builder.addRuleDefinition(new XcodeConfigRule()); - builder.addRuleDefinition(new IosTestRule()); - builder.addRuleDefinition(new IosDeviceRule()); - builder.addRuleDefinition(new AppleBinaryRule()); - builder.addRuleDefinition(new AppleStaticLibraryRule()); - builder.addRuleDefinition(new AppleDynamicLibraryRule()); - builder.addRuleDefinition(new ObjcBinaryRule()); - builder.addRuleDefinition(new ExperimentalObjcLibraryRule()); - builder.addRuleDefinition(new ObjcBundleRule()); - builder.addRuleDefinition(new ObjcBundleLibraryRule()); - builder.addRuleDefinition(new ObjcFrameworkRule()); - builder.addRuleDefinition(new ObjcImportRule()); - builder.addRuleDefinition(new ObjcLibraryRule()); - builder.addRuleDefinition(new ObjcProtoLibraryRule(objcProtoAspect)); - builder.addRuleDefinition(new ObjcXcodeprojRule()); - builder.addRuleDefinition(new ObjcRuleClasses.CoptsRule()); - builder.addRuleDefinition(new ObjcRuleClasses.BundlingRule()); - builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingRule()); - builder.addRuleDefinition(new ObjcRuleClasses.SimulatorRule()); - builder.addRuleDefinition(new ObjcRuleClasses.CompilingRule()); - builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule(objcProtoAspect)); - builder.addRuleDefinition(new ObjcRuleClasses.MultiArchPlatformRule()); - builder.addRuleDefinition(new ObjcRuleClasses.ResourcesRule()); - builder.addRuleDefinition(new ObjcRuleClasses.XcodegenRule()); - builder.addRuleDefinition(new ObjcRuleClasses.AlwaysLinkRule()); - builder.addRuleDefinition(new ObjcRuleClasses.SdkFrameworksDependerRule()); - builder.addRuleDefinition(new ObjcRuleClasses.CompileDependencyRule()); - builder.addRuleDefinition(new ObjcRuleClasses.ResourceToolsRule()); - builder.addRuleDefinition(new ObjcRuleClasses.XcrunRule()); - builder.addRuleDefinition(new ObjcRuleClasses.LibtoolRule()); - builder.addRuleDefinition(new ObjcRuleClasses.IpaRule()); - builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingToolsRule()); - builder.addRuleDefinition(new ObjcRuleClasses.WatchExtensionBundleRule()); - builder.addRuleDefinition(new ObjcRuleClasses.WatchApplicationBundleRule()); - builder.addRuleDefinition(new ObjcRuleClasses.CrosstoolRule()); - builder.addRuleDefinition(new AppleWatch1ExtensionRule()); - builder.addRuleDefinition(new AppleWatch2ExtensionRule()); - builder.addRuleDefinition(new AppleWatchExtensionBinaryRule()); - builder.addRuleDefinition(new IosApplicationRule()); - builder.addRuleDefinition(new IosExtensionBinaryRule()); - builder.addRuleDefinition(new IosExtensionRule()); - builder.addRuleDefinition(new IosFrameworkBinaryRule()); - builder.addRuleDefinition(new IosFrameworkRule()); - builder.addRuleDefinition(new XcodeVersionRule()); - builder.addRuleDefinition(new J2ObjcLibraryBaseRule()); - builder.addRuleDefinition(new BazelJ2ObjcLibraryRule(j2ObjcAspect)); - - builder.addRuleDefinition(new GitRepositoryRule()); - builder.addRuleDefinition(new HttpArchiveRule()); - builder.addRuleDefinition(new HttpJarRule()); - builder.addRuleDefinition(new HttpFileRule()); - builder.addRuleDefinition(new MavenJarRule()); - builder.addRuleDefinition(new MavenServerRule()); - builder.addRuleDefinition(new NewHttpArchiveRule()); - builder.addRuleDefinition(new NewGitRepositoryRule()); - builder.addRuleDefinition(new NewLocalRepositoryRule()); - builder.addRuleDefinition(new AndroidSdkRepositoryRule()); - builder.addRuleDefinition(new AndroidNdkRepositoryRule()); - builder.addRuleDefinition(new BazelJavaProtoLibraryRule(bazelJavaProtoAspect)); - builder.addRuleDefinition(new BazelJavaLiteProtoLibraryRule(bazelJavaLiteProtoAspect)); - - builder.addConfigurationOptions(AppleCommandLineOptions.class); - builder.addConfigurationFragment(new AppleConfiguration.Loader()); - builder.addConfigurationFragment(new PythonConfigurationLoader()); - builder.addConfigurationFragment(new BazelPythonConfiguration.Loader()); - builder.addConfigurationFragment(new ObjcConfigurationLoader()); - builder.addConfigurationFragment(new J2ObjcConfiguration.Loader()); - - builder.addSkylarkAccessibleTopLevels("apple_common", new AppleSkylarkCommon()); - } + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES, CPP_RULES); + } + }; + + public static final RuleModule JAVA_PROTO_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + BazelJavaProtoAspect bazelJavaProtoAspect = new BazelJavaProtoAspect(); + BazelJavaLiteProtoAspect bazelJavaLiteProtoAspect = new BazelJavaLiteProtoAspect(); + builder.addNativeAspectClass(bazelJavaProtoAspect); + builder.addNativeAspectClass(bazelJavaLiteProtoAspect); + builder.addRuleDefinition(new BazelJavaProtoLibraryRule(bazelJavaProtoAspect)); + builder.addRuleDefinition(new BazelJavaLiteProtoLibraryRule(bazelJavaLiteProtoAspect)); + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES, JAVA_RULES); + } + }; + + public static final RuleModule ANDROID_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + String toolsRepository = checkNotNull(builder.getToolsRepository()); + + builder.addConfigurationOptions(AndroidConfiguration.Options.class); + builder.addConfigurationFragment(new AndroidConfiguration.Loader()); + + AndroidNeverlinkAspect androidNeverlinkAspect = new AndroidNeverlinkAspect(); + DexArchiveAspect dexArchiveAspect = new DexArchiveAspect(toolsRepository); + JackAspect jackAspect = new JackAspect(toolsRepository); + builder.addNativeAspectClass(androidNeverlinkAspect); + builder.addNativeAspectClass(dexArchiveAspect); + builder.addNativeAspectClass(jackAspect); + + builder.addRuleDefinition(new AndroidRuleClasses.AndroidSdkRule()); + builder.addRuleDefinition(new BazelAndroidToolsDefaultsJarRule()); + builder.addRuleDefinition(new AndroidRuleClasses.AndroidBaseRule()); + builder.addRuleDefinition(new AndroidRuleClasses.AndroidAaptBaseRule()); + builder.addRuleDefinition(new AndroidRuleClasses.AndroidResourceSupportRule()); + builder.addRuleDefinition(new AndroidRuleClasses.AndroidBinaryBaseRule( + androidNeverlinkAspect, dexArchiveAspect, jackAspect)); + builder.addRuleDefinition(new AndroidBinaryOnlyRule()); + builder.addRuleDefinition(new AndroidLibraryBaseRule(androidNeverlinkAspect, jackAspect)); + builder.addRuleDefinition(new BazelAndroidLibraryRule()); + builder.addRuleDefinition(new BazelAndroidBinaryRule()); + builder.addRuleDefinition(new AarImportBaseRule()); + builder.addRuleDefinition(new BazelAarImportRule()); + + builder.addSkylarkAccessibleTopLevels("android_common", new AndroidSkylarkCommon()); + + try { + builder.addWorkspaceFilePrefix( + ResourceFileLoader.loadResource(BazelAndroidSemantics.class, "android.WORKSPACE")); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES, CPP_RULES, JAVA_RULES); + } + }; + + public static final RuleModule PYTHON_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + builder.addConfigurationOptions(PythonOptions.class); + builder.addConfigurationOptions(BazelPythonConfiguration.Options.class); + builder.addConfigurationFragment(new PythonConfigurationLoader()); + builder.addConfigurationFragment(new BazelPythonConfiguration.Loader()); + + builder.addRuleDefinition(new BazelPyRuleClasses.PyBaseRule()); + builder.addRuleDefinition(new BazelPyRuleClasses.PyBinaryBaseRule()); + builder.addRuleDefinition(new BazelPyLibraryRule()); + builder.addRuleDefinition(new BazelPyBinaryRule()); + builder.addRuleDefinition(new BazelPyTestRule()); + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES, CPP_RULES); + } + }; + + public static final RuleModule OBJC_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + String toolsRepository = checkNotNull(builder.getToolsRepository()); + + builder.addConfigurationOptions(ObjcCommandLineOptions.class); + builder.addConfigurationOptions(AppleCommandLineOptions.class); + builder.addConfigurationFragment(new ObjcConfigurationLoader()); + builder.addConfigurationFragment(new AppleConfiguration.Loader()); + + builder.addBuildInfoFactory(new ObjcBuildInfoFactory()); + builder.registerSkylarkProvider( + ObjcProvider.OBJC_SKYLARK_PROVIDER_NAME, ObjcProvider.class); + + builder.addSkylarkAccessibleTopLevels("apple_common", new AppleSkylarkCommon()); + + // objc_proto_library should go into a separate RuleModule! + ObjcProtoAspect objcProtoAspect = new ObjcProtoAspect(); + builder.addNativeAspectClass(objcProtoAspect); + builder.addRuleDefinition(new ObjcProtoLibraryRule(objcProtoAspect)); + + builder.addRuleDefinition(new AppleCcToolchainRule()); + builder.addRuleDefinition(new AppleToolchain.RequiresXcodeConfigRule(toolsRepository)); + builder.addRuleDefinition(new XcodeConfigRule()); + builder.addRuleDefinition(new IosTestRule()); + builder.addRuleDefinition(new IosDeviceRule()); + builder.addRuleDefinition(new AppleBinaryRule()); + builder.addRuleDefinition(new AppleStaticLibraryRule()); + builder.addRuleDefinition(new AppleDynamicLibraryRule()); + builder.addRuleDefinition(new ObjcBinaryRule()); + builder.addRuleDefinition(new ExperimentalObjcLibraryRule()); + builder.addRuleDefinition(new ObjcBundleRule()); + builder.addRuleDefinition(new ObjcBundleLibraryRule()); + builder.addRuleDefinition(new ObjcFrameworkRule()); + builder.addRuleDefinition(new ObjcImportRule()); + builder.addRuleDefinition(new ObjcLibraryRule()); + builder.addRuleDefinition(new ObjcXcodeprojRule()); + builder.addRuleDefinition(new ObjcRuleClasses.CoptsRule()); + builder.addRuleDefinition(new ObjcRuleClasses.BundlingRule()); + builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingRule()); + builder.addRuleDefinition(new ObjcRuleClasses.SimulatorRule()); + builder.addRuleDefinition(new ObjcRuleClasses.CompilingRule()); + // TODO(ulfjack): Depending on objcProtoAspect from here is a layering violation. + builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule(objcProtoAspect)); + builder.addRuleDefinition(new ObjcRuleClasses.MultiArchPlatformRule()); + builder.addRuleDefinition(new ObjcRuleClasses.ResourcesRule()); + builder.addRuleDefinition(new ObjcRuleClasses.XcodegenRule()); + builder.addRuleDefinition(new ObjcRuleClasses.AlwaysLinkRule()); + builder.addRuleDefinition(new ObjcRuleClasses.SdkFrameworksDependerRule()); + builder.addRuleDefinition(new ObjcRuleClasses.CompileDependencyRule()); + builder.addRuleDefinition(new ObjcRuleClasses.ResourceToolsRule()); + builder.addRuleDefinition(new ObjcRuleClasses.XcrunRule()); + builder.addRuleDefinition(new ObjcRuleClasses.LibtoolRule()); + builder.addRuleDefinition(new ObjcRuleClasses.IpaRule()); + builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingToolsRule()); + builder.addRuleDefinition(new ObjcRuleClasses.WatchExtensionBundleRule()); + builder.addRuleDefinition(new ObjcRuleClasses.WatchApplicationBundleRule()); + builder.addRuleDefinition(new ObjcRuleClasses.CrosstoolRule()); + builder.addRuleDefinition(new AppleWatch1ExtensionRule()); + builder.addRuleDefinition(new AppleWatch2ExtensionRule()); + builder.addRuleDefinition(new AppleWatchExtensionBinaryRule()); + builder.addRuleDefinition(new IosApplicationRule()); + builder.addRuleDefinition(new IosExtensionBinaryRule()); + builder.addRuleDefinition(new IosExtensionRule()); + builder.addRuleDefinition(new IosFrameworkBinaryRule()); + builder.addRuleDefinition(new IosFrameworkRule()); + builder.addRuleDefinition(new XcodeVersionRule()); + + // j2objc also doesn't belong here. + builder.addConfigurationOptions(J2ObjcCommandLineOptions.class); + builder.addConfigurationFragment(new J2ObjcConfiguration.Loader()); + + BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect = + new BazelJ2ObjcProtoAspect(toolsRepository); + J2ObjcAspect j2ObjcAspect = new J2ObjcAspect(toolsRepository, bazelJ2ObjcProtoAspect); + + builder.addNativeAspectClass(bazelJ2ObjcProtoAspect); + builder.addNativeAspectClass(j2ObjcAspect); + builder.addRuleDefinition(new J2ObjcLibraryBaseRule()); + builder.addRuleDefinition(new BazelJ2ObjcLibraryRule(j2ObjcAspect)); + + try { + builder.addWorkspaceFilePrefix( + ResourceFileLoader.loadResource(BazelJ2ObjcLibraryRule.class, "j2objc.WORKSPACE")); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES, CPP_RULES, JAVA_RULES); + } + }; + + public static final RuleModule ANDROID_STUDIO_ASPECT = + new RuleModule() { + @Override + public void init(Builder builder) { + String toolsRepository = checkNotNull(builder.getToolsRepository()); + AndroidStudioInfoAspect androidStudioInfoAspect = + new AndroidStudioInfoAspect(toolsRepository, new BazelAndroidStudioInfoSemantics()); + builder.addNativeAspectClass(androidStudioInfoAspect); + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES); + } + }; + + public static final RuleModule VARIOUS_WORKSPACE_RULES = + new RuleModule() { + @Override + public void init(Builder builder) { + // TODO(ulfjack): Split this up by conceptual units. + builder.addRuleDefinition(new GitRepositoryRule()); + builder.addRuleDefinition(new HttpArchiveRule()); + builder.addRuleDefinition(new HttpJarRule()); + builder.addRuleDefinition(new HttpFileRule()); + builder.addRuleDefinition(new MavenJarRule()); + builder.addRuleDefinition(new MavenServerRule()); + builder.addRuleDefinition(new NewHttpArchiveRule()); + builder.addRuleDefinition(new NewGitRepositoryRule()); + builder.addRuleDefinition(new NewLocalRepositoryRule()); + builder.addRuleDefinition(new AndroidSdkRepositoryRule()); + builder.addRuleDefinition(new AndroidNdkRepositoryRule()); + } + + @Override + public ImmutableList<RuleModule> requires() { + return ImmutableList.of(MINIMAL_RULES); + } + }; } diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD index 859e0a8a97..942d9a337d 100644 --- a/src/test/java/com/google/devtools/build/lib/BUILD +++ b/src/test/java/com/google/devtools/build/lib/BUILD @@ -962,6 +962,7 @@ java_test( "//src/main/java/com/google/devtools/build/lib:build-base", "//src/main/java/com/google/devtools/build/lib:events", "//src/main/java/com/google/devtools/build/lib:java-compilation", + "//src/main/java/com/google/devtools/build/lib:packages-internal", "//src/main/java/com/google/devtools/build/lib:util", "//src/main/java/com/google/devtools/build/lib:vfs", "//src/main/java/com/google/devtools/build/lib/actions", diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProviderTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProviderTest.java new file mode 100644 index 0000000000..fb1617fa8e --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProviderTest.java @@ -0,0 +1,130 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.bazel.rules; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; +import com.google.devtools.build.lib.analysis.config.BuildConfiguration; +import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; +import com.google.devtools.build.lib.analysis.config.FragmentOptions; +import com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider.RuleModule; +import com.google.devtools.build.lib.packages.RuleClass; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests consistency of {@link BazelRuleClassProvider}. + */ +@RunWith(JUnit4.class) +public class BazelRuleClassProviderTest { + private void checkConfigConsistency(ConfiguredRuleClassProvider provider) { + // Check that every fragment required by a rule is present. + Set<Class<? extends BuildConfiguration.Fragment>> configurationFragments = + provider.getAllFragments(); + for (RuleClass ruleClass : provider.getRuleClassMap().values()) { + for (Class<?> fragment : + ruleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments()) { + assertWithMessage(ruleClass.toString()).that(configurationFragments).contains(fragment); + } + } + + List<Class<? extends FragmentOptions>> configOptions = provider.getConfigurationOptions(); + for (ConfigurationFragmentFactory fragmentFactory : provider.getConfigurationFragments()) { + // Check that every created fragment is present. + assertThat(configurationFragments).contains(fragmentFactory.creates()); + // Check that every options class required for fragment creation is provided. + for (Class<? extends FragmentOptions> options : fragmentFactory.requiredOptions()) { + assertThat(configOptions).contains(options); + } + } + } + + private void checkModule(RuleModule top) { + ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder(); + builder.setToolsRepository(BazelRuleClassProvider.TOOLS_REPOSITORY); + Set<RuleModule> result = new HashSet<>(); + collectTransitiveClosure(result, top); + for (RuleModule module : result) { + module.init(builder); + } + ConfiguredRuleClassProvider provider = builder.build(); + assertThat(provider).isNotNull(); + checkConfigConsistency(provider); + } + + private void collectTransitiveClosure(Set<RuleModule> result, RuleModule module) { + if (result.add(module)) { + for (RuleModule dep : module.requires()) { + collectTransitiveClosure(result, dep); + } + } + } + + @Test + public void minimalConsistency() { + checkModule(BazelRuleClassProvider.MINIMAL_RULES); + } + + @Test + public void shConsistency() { + checkModule(BazelRuleClassProvider.SH_RULES); + } + + @Test + public void protoConsistency() { + checkModule(BazelRuleClassProvider.PROTO_RULES); + } + + @Test + public void cppConsistency() { + checkModule(BazelRuleClassProvider.CPP_RULES); + } + + @Test + public void javaConsistency() { + checkModule(BazelRuleClassProvider.JAVA_RULES); + } + + @Test + public void pythonConsistency() { + checkModule(BazelRuleClassProvider.PYTHON_RULES); + } + + @Test + public void androidConsistency() { + checkModule(BazelRuleClassProvider.ANDROID_RULES); + } + + @Test + public void objcConsistency() { + checkModule(BazelRuleClassProvider.OBJC_RULES); + } + + @Test + public void androidStudioConsistency() { + checkModule(BazelRuleClassProvider.ANDROID_STUDIO_ASPECT); + } + + @Test + public void variousWorkspaceConsistency() { + checkModule(BazelRuleClassProvider.VARIOUS_WORKSPACE_RULES); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java index da6e3b7267..cf6de2c6c1 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java @@ -830,8 +830,8 @@ public class CcCommonTest extends BuildViewTestCase { public ConfiguredRuleClassProvider createRuleClassProvider() { ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder(); builder.setToolsRepository("@bazel_tools"); - BazelRuleClassProvider.initMinimal(builder); - BazelRuleClassProvider.initCpp(builder); + BazelRuleClassProvider.MINIMAL_RULES.init(builder); + BazelRuleClassProvider.CPP_RULES.init(builder); return builder.build(); } |