private static AndroidBuildConfig createSimpleBuildConfigRule() { // First, create the BuildConfig object. BuildTarget buildTarget = BuildTarget.builder("//java/com/example", "build_config").build(); BuildRuleParams params = new FakeBuildRuleParamsBuilder(buildTarget).build(); return new AndroidBuildConfig( params, new SourcePathResolver(new BuildRuleResolver()), /* javaPackage */ "com.example", /* values */ BuildConfigFields.empty(), /* valuesFile */ Optional.<SourcePath>absent(), /* useConstantExpressions */ false); }
@Test public void testBuildInternal() throws IOException { AndroidBuildConfig buildConfig = createSimpleBuildConfigRule(); List<Step> steps = buildConfig.getBuildSteps(FakeBuildContext.NOOP_CONTEXT, new FakeBuildableContext()); Step generateBuildConfigStep = steps.get(1); GenerateBuildConfigStep expectedStep = new GenerateBuildConfigStep( new FakeProjectFilesystem(), /* source */ BuildTargetFactory.newInstance("//java/com/example:build_config"), /* javaPackage */ "com.example", /* useConstantExpressions */ false, /* constants */ Suppliers.ofInstance(BuildConfigFields.empty()), BuckConstant.GEN_PATH.resolve("java/com/example/__build_config__/BuildConfig.java")); assertEquals(expectedStep, generateBuildConfigStep); }
@Test @SuppressWarnings("PMD.UseAssertTrueInsteadOfAssertEquals") // PMD has a bad heuristic here. public void testReadValuesStep() throws IOException { Path pathToValues = Paths.get("src/values.txt"); ProjectFilesystem projectFilesystem = EasyMock.createMock(ProjectFilesystem.class); EasyMock.expect(projectFilesystem.readLines(pathToValues)) .andReturn(ImmutableList.of("boolean DEBUG = false", "String FOO = \"BAR\"")); EasyMock.replay(projectFilesystem); ReadValuesStep step = new ReadValuesStep(projectFilesystem, pathToValues); ExecutionContext context = TestExecutionContext.newBuilder().build(); int exitCode = step.execute(context); assertEquals(0, exitCode); assertEquals( BuildConfigFields.fromFields( ImmutableList.of( BuildConfigFields.Field.of("boolean", "DEBUG", "false"), BuildConfigFields.Field.of("String", "FOO", "\"BAR\""))), step.get()); EasyMock.verify(projectFilesystem); }
@Override public <A extends Arg> BuildRule createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) { BuildRule installableApk = resolver.getRule(args.apk); if (!(installableApk instanceof InstallableApk)) { throw new HumanReadableException( "In %s, apk='%s' must be an android_binary() or apk_genrule() but was %s().", params.getBuildTarget(), installableApk.getFullyQualifiedName(), installableApk.getType()); } AndroidBinary apkUnderTest = getUnderlyingApk((InstallableApk) installableApk); ImmutableSortedSet<JavaLibrary> rulesToExcludeFromDex = FluentIterable.from( ImmutableSet.<JavaLibrary>builder() .addAll(apkUnderTest.getRulesToExcludeFromDex()) .addAll( Classpaths.getClasspathEntries(apkUnderTest.getClasspathDeps()).keySet()) .build()) .toSortedSet(HasBuildTarget.BUILD_TARGET_COMPARATOR); // TODO(natthu): Instrumentation APKs should also exclude native libraries and assets from the // apk under test. AndroidPackageableCollection.ResourceDetails resourceDetails = apkUnderTest.getAndroidPackageableCollection().getResourceDetails(); ImmutableSet<BuildTarget> resourcesToExclude = ImmutableSet.copyOf( Iterables.concat( resourceDetails.getResourcesWithNonEmptyResDir(), resourceDetails.getResourcesWithEmptyResButNonEmptyAssetsDir())); Path primaryDexPath = AndroidBinary.getPrimaryDexPath(params.getBuildTarget()); AndroidBinaryGraphEnhancer graphEnhancer = new AndroidBinaryGraphEnhancer( targetGraph, params, resolver, ResourceCompressionMode.DISABLED, FilterResourcesStep.ResourceFilter.EMPTY_FILTER, /* resourceUnionPackage */ Optional.<String>absent(), /* locales */ ImmutableSet.<String>of(), args.manifest, PackageType.INSTRUMENTED, apkUnderTest.getCpuFilters(), /* shouldBuildStringSourceMap */ false, /* shouldPreDex */ false, primaryDexPath, DexSplitMode.NO_SPLIT, FluentIterable.from(rulesToExcludeFromDex).transform(TO_TARGET).toSet(), resourcesToExclude, /* skipCrunchPngs */ false, javacOptions, EnumSet.noneOf(ExopackageMode.class), apkUnderTest.getKeystore(), /* buildConfigValues */ BuildConfigFields.empty(), /* buildConfigValuesFile */ Optional.<SourcePath>absent(), /* xzCompressionLevel */ Optional.<Integer>absent(), nativePlatforms, dxExecutorService); AndroidGraphEnhancementResult enhancementResult = graphEnhancer.createAdditionalBuildables(); return new AndroidInstrumentationApk( params .copyWithExtraDeps(Suppliers.ofInstance(enhancementResult.getFinalDeps())) .appendExtraDeps(rulesToExcludeFromDex), new SourcePathResolver(resolver), proGuardConfig.getProguardJarOverride(), proGuardConfig.getProguardMaxHeapSize(), apkUnderTest, rulesToExcludeFromDex, enhancementResult, dxExecutorService); }
/** * If the user specified any android_build_config() rules, then we must add some build rules to * generate the production {@code BuildConfig.class} files and ensure that they are included in * the list of {@link AndroidPackageableCollection#getClasspathEntriesToDex}. */ private void addBuildConfigDeps( boolean shouldPreDex, AndroidPackageableCollection packageableCollection, ImmutableSortedSet.Builder<BuildRule> enhancedDeps, ImmutableList.Builder<DexProducedFromJavaLibrary> preDexRules, ImmutableList.Builder<Path> buildConfigJarFilesBuilder) { BuildConfigFields buildConfigConstants = BuildConfigFields.fromFields( ImmutableList.<BuildConfigFields.Field>of( BuildConfigFields.Field.of( "boolean", BuildConfigs.DEBUG_CONSTANT, String.valueOf(packageType != AndroidBinary.PackageType.RELEASE)), BuildConfigFields.Field.of( "boolean", BuildConfigs.IS_EXO_CONSTANT, String.valueOf(!exopackageModes.isEmpty())), BuildConfigFields.Field.of( "int", BuildConfigs.EXOPACKAGE_FLAGS, String.valueOf(ExopackageMode.toBitmask(exopackageModes))))); for (Map.Entry<String, BuildConfigFields> entry : packageableCollection.getBuildConfigs().entrySet()) { // Merge the user-defined constants with the APK-specific overrides. BuildConfigFields totalBuildConfigValues = BuildConfigFields.empty() .putAll(entry.getValue()) .putAll(buildConfigValues) .putAll(buildConfigConstants); // Each enhanced dep needs a unique build target, so we parameterize the build target by the // Java package. String javaPackage = entry.getKey(); Flavor flavor = ImmutableFlavor.of("buildconfig_" + javaPackage.replace('.', '_')); BuildRuleParams buildConfigParams = new BuildRuleParams( createBuildTargetWithFlavor(flavor), /* declaredDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()), buildRuleParams.getProjectFilesystem(), buildRuleParams.getRuleKeyBuilderFactory()); JavaLibrary buildConfigJavaLibrary = AndroidBuildConfigDescription.createBuildRule( buildConfigParams, javaPackage, totalBuildConfigValues, buildConfigValuesFile, /* useConstantExpressions */ true, javacOptions, ruleResolver); ruleResolver.addToIndex(buildConfigJavaLibrary); enhancedDeps.add(buildConfigJavaLibrary); Path buildConfigJar = buildConfigJavaLibrary.getPathToOutput(); Preconditions.checkNotNull( buildConfigJar, "%s must have an output file.", buildConfigJavaLibrary); buildConfigJarFilesBuilder.add(buildConfigJar); if (shouldPreDex) { DexProducedFromJavaLibrary buildConfigDex = new DexProducedFromJavaLibrary( buildConfigParams.copyWithChanges( createBuildTargetWithFlavor(ImmutableFlavor.of("dex_" + flavor.getName())), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(buildConfigJavaLibrary)), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), pathResolver, buildConfigJavaLibrary); ruleResolver.addToIndex(buildConfigDex); enhancedDeps.add(buildConfigDex); preDexRules.add(buildConfigDex); } } }