com.android.build.api.transform.Transform Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
APIs to customize Android Gradle Builds
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.android.build.api.transform;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.api.transform.QualifiedContent.ContentType;
import com.android.build.api.transform.QualifiedContent.Scope;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* A Transform that processes intermediary build artifacts.
*
* For each added transform, a new task is created. The action of adding a transform takes
* care of handling dependencies between the tasks. This is done based on what the transform
* processes. The output of the transform becomes consumable by other transforms and these
* tasks get automatically linked together.
*
* The Transform indicates what it applies to (content, scope) and what it generates (content).
*
* A transform receives input as a collection {@link TransformInput}, which is composed of
* {@link JarInput}s and {@link DirectoryInput}s.
* Both provide information about the {@link Scope}s and {@link ContentType}s associated with their
* particular content.
*
* The output is handled by {@link TransformOutputProvider} which allows creating new self-contained
* content, each associated with their own Scopes and Content Types.
* The content handled by TransformInput/Output is managed by the transform system, and their
* location is not configurable.
*
* It is best practice to write into as many outputs as Jar/Folder Inputs have been received by the
* transform. Combining all the inputs into a single output prevents downstream transform from
* processing limited scopes.
*
* While it's possible to differentiate different Content Types by file extension, it's not possible
* to do so for Scopes. Therefore if a transform request a Scope but the only available Output
* contains more than the requested Scope, the build will fail.
* If a transform request a single content type but the only available content includes more than
* the requested type, the input file/folder will contain all the files of all the types, but
* the transform should only read, process and output the type(s) it requested.
*
*
* Additionally, a transform can indicate secondary inputs/outputs. These are not handled by
* upstream or downstream transforms, and are not restricted by type handled by transform. They can
* be anything.
* It's up to each transform to manage where these files are, and to make sure that these files
* are generated before the transform is called. This is done through additional parameters
* when register the transform.
* These secondary inputs/outputs allow a transform to read but not process any content. This
* can be achieved by having {@link #getScopes()} return an empty list and use
* {@link #getReferencedScopes()} to indicate what to read instead.
*
*
* This API is non final and is subject to change. We are looking for feedback, and will
* attempt to stabilize it in the 1.6 time frame.
*/
@Beta
@SuppressWarnings("MethodMayBeStatic")
public abstract class Transform {
/**
* Returns the unique name of the transform.
*
*
* This is associated with the type of work that the transform does. It does not have to be
* unique per variant.
*/
@NonNull
public abstract String getName();
/**
* Returns the type(s) of data that is consumed by the Transform. This may be more than
* one type.
*
* This must be of type {@link QualifiedContent.DefaultContentType}
*/
@NonNull
public abstract Set getInputTypes();
/**
* Returns the type(s) of data that is generated by the Transform. This may be more than
* one type.
*
*
* The default implementation returns {@link #getInputTypes()}.
*
* This must be of type {@link QualifiedContent.DefaultContentType}
*/
@NonNull
public Set getOutputTypes() {
return getInputTypes();
}
/**
* Returns the scope(s) of the Transform. This indicates which scopes the transform consumes.
*/
@NonNull
public abstract Set getScopes();
/**
* Returns the referenced scope(s) for the Transform. These scopes are not consumed by
* the Transform. They are provided as inputs, but are still available as inputs for
* other Transforms to consume.
*
*
* The default implementation returns an empty Set.
*/
@NonNull
public Set getReferencedScopes() {
return ImmutableSet.of();
}
/**
* Returns a list of additional file(s) that this Transform needs to run. Preferably, use
* {@link #getSecondaryFiles()} API which allow eah secondary file to indicate if changes
* can be handled incrementally or not. This API will treat all additional file change as
* a non incremental event.
*
*
* Changes to files returned in this list will trigger a new execution of the Transform
* even if the qualified-content inputs haven't been touched.
*
* Any changes to these files will trigger a non incremental execution.
*
*
* The default implementation returns an empty collection.
* @deprecated
*/
@Deprecated
@NonNull
public Collection getSecondaryFileInputs() {
return ImmutableList.of();
}
/**
* Returns a list of additional file(s) that this Transform needs to run.
*
*
* Changes to files returned in this list will trigger a new execution of the Transform
* even if the qualified-content inputs haven't been touched.
*
* Each secondary input has the ability to be declared as necessitating a non incremental
* execution in case of change. This Transform can therefore declare which secondary file
* changes it supports in incremental mode.
*
*
* The default implementation returns an empty collection.
*
* @return
*/
@NonNull
public Collection getSecondaryFiles() {
return ImmutableList.of();
}
/**
* Returns a list of additional (out of streams) file(s) that this Transform creates.
*
*
* These File instances can only represent files, not directories. For directories, use
* {@link #getSecondaryDirectoryOutputs()}
*
*
* Changes to files returned in this list will trigger a new execution of the Transform
* even if the qualified-content inputs haven't been touched.
*
* Changes to these output files force a non incremental execution.
*
*
* The default implementation returns an empty collection.
*/
@NonNull
public Collection getSecondaryFileOutputs() {
return ImmutableList.of();
}
/**
* Returns a list of additional (out of streams) directory(ies) that this Transform creates.
*
*
* These File instances can only represent directories. For files, use
* {@link #getSecondaryFileOutputs()}
*
*
* Changes to directories returned in this list will trigger a new execution of the Transform
* even if the qualified-content inputs haven't been touched.
*
* Changes to these output directories force a non incremental execution.
*
*
* The default implementation returns an empty collection.
*/
@NonNull
public Collection getSecondaryDirectoryOutputs() {
return ImmutableList.of();
}
/**
* Returns a map of non-file input parameters using a unique identifier as the map key.
*
*
* Changes to values returned in this map will trigger a new execution of the Transform
* even if the content inputs haven't been touched.
*
* Changes to these values force a non incremental execution.
*
*
* The default implementation returns an empty Map.
*/
@NonNull
public Map getParameterInputs() {
return ImmutableMap.of();
}
/**
* Returns whether the Transform can perform incremental work.
*
*
* If it does, then the TransformInput may contain a list of changed/removed/added files, unless
* something else triggers a non incremental run.
*/
public abstract boolean isIncremental();
/**
* @deprecated
*/
@Deprecated
public void transform(
@NonNull Context context,
@NonNull Collection inputs,
@NonNull Collection referencedInputs,
@Nullable TransformOutputProvider outputProvider,
boolean isIncremental) throws IOException, TransformException, InterruptedException {
}
/**
* Executes the Transform.
*
*
* The inputs are packaged as an instance of {@link TransformInvocation}
*
* - The inputs collection of {@link TransformInput}. These are the inputs
* that are consumed by this Transform. A transformed version of these inputs must
* be written into the output. What is received is controlled through
* {@link #getInputTypes()}, and {@link #getScopes()}.
* - The referencedInputs collection of {@link TransformInput}. This is
* for reference only and should be not be transformed. What is received is controlled
* through {@link #getReferencedScopes()}.
*
*
* A transform that does not want to consume anything but instead just wants to see the content
* of some inputs should return an empty set in {@link #getScopes()}, and what it wants to
* see in {@link #getReferencedScopes()}.
*
*
* Even though a transform's {@link Transform#isIncremental()} returns true, this method may
* be receive false
in isIncremental. This can be due to
*
* - a change in secondary files ({@link #getSecondaryFiles()},
* {@link #getSecondaryFileOutputs()}, {@link #getSecondaryDirectoryOutputs()})
* - a change to a non file input ({@link #getParameterInputs()})
* - an unexpected change to the output files/directories. This should not happen unless
* tasks are improperly configured and clobber each other's output.
* - a file deletion that the transform mechanism could not match to a previous input.
* This should not happen in most case, except in some cases where dependencies have
* changed.
*
* In such an event, when isIncremental is false, the inputs will not have any
* incremental change information:
*
* - {@link JarInput#getStatus()} will return {@link Status#NOTCHANGED} even though
* the file may be added/changed.
* - {@link DirectoryInput#getChangedFiles()} will return an empty map even though
* some files may be added/changed.
*
*
* @param transformInvocation the invocation object containing the transform inputs.
* @throws IOException if an IO error occurs.
* @throws InterruptedException
* @throws TransformException Generic exception encapsulating the cause.
*/
public void transform(@NonNull TransformInvocation transformInvocation)
throws TransformException, InterruptedException, IOException {
transform(transformInvocation.getContext(), transformInvocation.getInputs(),
transformInvocation.getReferencedInputs(),
transformInvocation.getOutputProvider(),
transformInvocation.isIncremental());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy