blob: 60b2e50bd9d249cb5d88b50b348aabcd7770776f [file] [log] [blame]
/*
* Copyright (C) 2010, 2012 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.ant;
import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.build.ManualRenderScriptChecker;
import com.android.sdklib.build.RenderScriptProcessor;
import com.android.sdklib.repository.FullRevision;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.ExecTask;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.Path;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Task to execute renderscript.
* <p>
* It expects 7 attributes:<br>
* 'buildToolsRoot' ({@link Path} with a single path) for the location of the build tools<br>
* 'framework' ({@link Path} with 1 or more paths) for the include paths.<br>
* 'genFolder' ({@link Path} with a single path) for the location of the gen folder.<br>
* 'resFolder' ({@link Path} with a single path) for the location of the res folder.<br>
* 'targetApi' for the -target-api value.<br>
* 'optLevel' for the -O optimization level.<br>
* 'debug' for -g renderscript debugging.<br>
* <p>
* It also expects one or more inner elements called "source" which are identical to {@link Path}
* elements for where to find .rs files.
*/
public class RenderScriptTask extends BuildTypedTask {
private static final Set<String> EXTENSIONS = Sets.newHashSetWithExpectedSize(2);
static {
EXTENSIONS.add(SdkConstants.EXT_RS);
EXTENSIONS.add(SdkConstants.EXT_FS);
}
private String mBuildToolsRoot;
private String mGenFolder;
private String mResFolder;
private String mRsObjFolder;
private String mLibsFolder;
private String mBinFolder;
private final List<Path> mPaths = new ArrayList<Path>();
private int mTargetApi = 0;
private boolean mSupportMode = false;
public enum OptLevel { O0, O1, O2, O3 }
private OptLevel mOptLevel;
private boolean mDebug = false;
/**
* Sets the value of the "buildToolsRoot" attribute.
* @param buildToolsRoot the value.
*/
public void setBuildToolsRoot(Path buildToolsRoot) {
mBuildToolsRoot = TaskHelper.checkSinglePath("buildToolsRoot", buildToolsRoot);
}
public void setGenFolder(Path value) {
mGenFolder = TaskHelper.checkSinglePath("genFolder", value);
}
public void setResFolder(Path value) {
mResFolder = TaskHelper.checkSinglePath("resFolder", value);
}
public void setRsObjFolder(Path value) {
mRsObjFolder = TaskHelper.checkSinglePath("rsObjFolder", value);
}
public void setLibsFolder(Path value) {
mLibsFolder = TaskHelper.checkSinglePath("libsFolder", value);
}
public void setTargetApi(String targetApi) {
try {
mTargetApi = Integer.parseInt(targetApi);
if (mTargetApi <= 0) {
throw new BuildException("targetApi attribute value must be >= 1");
}
} catch (NumberFormatException e) {
throw new BuildException("targetApi attribute value must be an integer", e);
}
}
public void setOptLevel(OptLevel optLevel) {
mOptLevel = optLevel;
}
public void setSupportMode(boolean supportMode) {
mSupportMode = supportMode;
}
public void setBinFolder(Path binFolder) {
mBinFolder = TaskHelper.checkSinglePath("binFolder", binFolder);
}
/** Sets the current build type. value is a boolean, true for debug build, false for release */
@Override
public void setBuildType(String buildType) {
super.setBuildType(buildType);
mDebug = Boolean.valueOf(buildType);
}
public Path createSource() {
Path p = new Path(getProject());
mPaths.add(p);
return p;
}
@Override
public void execute() throws BuildException {
if (mBuildToolsRoot == null) {
throw new BuildException("RenderScriptTask's 'buildToolsRoot' is required.");
}
if (mGenFolder == null) {
throw new BuildException("RenderScriptTask's 'genFolder' is required.");
}
if (mResFolder == null) {
throw new BuildException("RenderScriptTask's 'resFolder' is required.");
}
if (mRsObjFolder == null) {
throw new BuildException("RenderScriptTask's 'rsObjFolder' is required.");
}
if (mLibsFolder == null) {
throw new BuildException("RenderScriptTask's 'libsFolder' is required.");
}
if (mTargetApi == 0) {
throw new BuildException("RenderScriptTask's 'targetApi' is required.");
}
if (mBinFolder == null) {
throw new BuildException("RenderScriptTask's 'binFolder' is required.");
}
// convert the Path to List<File>
List<File> sourceFolders = Lists.newArrayList();
for (Path path : mPaths) {
String[] values = path.list();
if (values != null) {
for (String p : values) {
sourceFolders.add(new File(p));
}
}
}
try {
File binFile = new File(mBinFolder);
ManualRenderScriptChecker checker = new ManualRenderScriptChecker(
sourceFolders, binFile);
if (checker.mustCompile() || isNewBuild() || hasBuildTypeChanged()) {
checker.cleanDependencies();
List<File> emptyFileList = Collections.emptyList();
RenderScriptProcessor processor = new RenderScriptProcessor(
checker.getInputFiles(),
emptyFileList,
binFile,
new File(mGenFolder),
new File(mResFolder),
new File(mRsObjFolder),
new File(mLibsFolder),
new BuildToolInfo(new FullRevision(0), new File(mBuildToolsRoot)),
mTargetApi,
mDebug,
mOptLevel.ordinal(),
mSupportMode);
// clean old files first
processor.cleanOldOutput(checker.getOldOutputs());
// do the compilation(s).
processor.build(new RenderScriptProcessor.CommandLineLauncher() {
@Override
public void launch(
@NonNull File executable,
@NonNull List<String> arguments,
@NonNull Map<String, String> envVariableMap)
throws IOException, InterruptedException {
ExecTask task = new ExecTask();
task.setTaskName(executable.getName());
task.setProject(getProject());
task.setOwningTarget(getOwningTarget());
task.setExecutable(executable.getAbsolutePath());
task.setFailonerror(true);
// create the env var for the dynamic libraries
for (Map.Entry<String, String> entry : envVariableMap.entrySet()) {
Environment.Variable var = new Environment.Variable();
var.setKey(entry.getKey());
var.setValue(entry.getValue());
task.addEnv(var);
}
for (String arg : arguments) {
task.createArg().setValue(arg);
}
System.out.println(String.format(
"COMMAND: %s %s",
executable.getAbsolutePath(), Joiner.on(' ').join(arguments)));
task.execute();
}
});
}
} catch (IOException e) {
throw new BuildException(e);
} catch (InterruptedException e) {
throw new BuildException(e);
}
}
}