• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010, 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ant;
18 
19 import org.apache.tools.ant.BuildException;
20 import org.apache.tools.ant.Project;
21 import org.apache.tools.ant.taskdefs.ExecTask;
22 import org.apache.tools.ant.types.Path;
23 
24 import java.io.File;
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * Task to execute renderscript.
30  * <p>
31  * It expects 7 attributes:<br>
32  * 'executable' ({@link Path} with a single path) for the location of the llvm executable<br>
33  * 'framework' ({@link Path} with 1 or more paths) for the include paths.<br>
34  * 'genFolder' ({@link Path} with a single path) for the location of the gen folder.<br>
35  * 'resFolder' ({@link Path} with a single path) for the location of the res folder.<br>
36  * 'targetApi' for the -target-api value.<br>
37  * 'optLevel' for the -O optimization level.<br>
38  * 'debug' for -g renderscript debugging.<br>
39  * <p>
40  * It also expects one or more inner elements called "source" which are identical to {@link Path}
41  * elements for where to find .rs files.
42  */
43 public class RenderScriptTask extends MultiFilesTask {
44 
45     private String mExecutable;
46     private Path mIncludePath;
47     private String mGenFolder;
48     private String mResFolder;
49     private final List<Path> mPaths = new ArrayList<Path>();
50     private int mTargetApi = 0;
51     public enum OptLevel { O0, O1, O2, O3 };
52     private OptLevel mOptLevel;
53     private boolean mDebug = false;
54 
55     private class RenderScriptProcessor implements SourceProcessor {
56 
57         private final String mTargetApiStr;
58 
RenderScriptProcessor(int targetApi)59         public RenderScriptProcessor(int targetApi) {
60             // get the target api value. Must be 11+ or llvm-rs-cc complains.
61             mTargetApiStr = Integer.toString(mTargetApi < 11 ? 11 : mTargetApi);
62         }
63 
64         @Override
getSourceFileExtension()65         public String getSourceFileExtension() {
66             return "rs";
67         }
68 
69         @Override
process(String filePath, String sourceFolder, List<String> sourceFolders, Project taskProject)70         public void process(String filePath, String sourceFolder, List<String> sourceFolders,
71                 Project taskProject) {
72             File exe = new File(mExecutable);
73             String execTaskName = exe.getName();
74 
75             ExecTask task = new ExecTask();
76             task.setTaskName(execTaskName);
77             task.setProject(taskProject);
78             task.setOwningTarget(getOwningTarget());
79             task.setExecutable(mExecutable);
80             task.setFailonerror(true);
81 
82             for (String path : mIncludePath.list()) {
83                 File res = new File(path);
84                 if (res.isDirectory()) {
85                     task.createArg().setValue("-I");
86                     task.createArg().setValue(path);
87                 } else {
88                     System.out.println(String.format(
89                             "WARNING: RenderScript include directory '%s' does not exist!",
90                             res.getAbsolutePath()));
91                 }
92 
93             }
94 
95             if (mDebug) {
96                 task.createArg().setValue("-g");
97             }
98 
99             task.createArg().setValue("-O");
100             task.createArg().setValue(Integer.toString(mOptLevel.ordinal()));
101 
102             task.createArg().setValue("-target-api");
103             task.createArg().setValue(mTargetApiStr);
104 
105             task.createArg().setValue("-d");
106             task.createArg().setValue(getDependencyFolder(filePath, sourceFolder));
107             task.createArg().setValue("-MD");
108 
109             task.createArg().setValue("-p");
110             task.createArg().setValue(mGenFolder);
111             task.createArg().setValue("-o");
112             task.createArg().setValue(mResFolder);
113             task.createArg().setValue(filePath);
114 
115             // execute it.
116             task.execute();
117         }
118 
119         @Override
displayMessage(DisplayType type, int count)120         public void displayMessage(DisplayType type, int count) {
121             switch (type) {
122                 case FOUND:
123                     System.out.println(String.format("Found %1$d RenderScript files.", count));
124                     break;
125                 case COMPILING:
126                     if (count > 0) {
127                         System.out.println(String.format(
128                                 "Compiling %1$d RenderScript files with -target-api %2$d",
129                                 count, mTargetApi));
130                         System.out.println(String.format("Optimization Level: %1$d", mOptLevel.ordinal()));
131                     } else {
132                         System.out.println("No RenderScript files to compile.");
133                     }
134                     break;
135                 case REMOVE_OUTPUT:
136                     System.out.println(String.format("Found %1$d obsolete output files to remove.",
137                             count));
138                     break;
139                 case REMOVE_DEP:
140                     System.out.println(
141                             String.format("Found %1$d obsolete dependency files to remove.",
142                                     count));
143                     break;
144             }
145         }
146 
getDependencyFolder(String filePath, String sourceFolder)147         private String getDependencyFolder(String filePath, String sourceFolder) {
148             String relative = filePath.substring(sourceFolder.length());
149             if (relative.charAt(0) == '/') {
150                 relative = relative.substring(1);
151             }
152 
153             return new File(mGenFolder, relative).getParent();
154         }
155     }
156 
157 
158     /**
159      * Sets the value of the "executable" attribute.
160      * @param executable the value.
161      */
setExecutable(Path executable)162     public void setExecutable(Path executable) {
163         mExecutable = TaskHelper.checkSinglePath("executable", executable);
164     }
165 
setIncludePath(Path value)166     public void setIncludePath(Path value) {
167         mIncludePath = value;
168     }
169 
setGenFolder(Path value)170     public void setGenFolder(Path value) {
171         mGenFolder = TaskHelper.checkSinglePath("genFolder", value);
172     }
173 
setResFolder(Path value)174     public void setResFolder(Path value) {
175         mResFolder = TaskHelper.checkSinglePath("resFolder", value);
176     }
177 
setTargetApi(String targetApi)178     public void setTargetApi(String targetApi) {
179         try {
180             mTargetApi = Integer.parseInt(targetApi);
181             if (mTargetApi <= 0) {
182                 throw new BuildException("targetApi attribute value must be >= 1");
183             }
184         } catch (NumberFormatException e) {
185             throw new BuildException("targetApi attribute value must be an integer", e);
186         }
187     }
188 
setOptLevel(OptLevel optLevel)189     public void setOptLevel(OptLevel optLevel) {
190         mOptLevel = optLevel;
191     }
192 
193     /** Sets the current build type. value is a boolean, true for debug build, false for release */
194     @Override
setBuildType(String buildType)195     public void setBuildType(String buildType) {
196         super.setBuildType(buildType);
197         mDebug = Boolean.valueOf(buildType);
198     }
199 
createSource()200     public Path createSource() {
201         Path p = new Path(getProject());
202         mPaths.add(p);
203         return p;
204     }
205 
206     @Override
execute()207     public void execute() throws BuildException {
208         if (mExecutable == null) {
209             throw new BuildException("RenderScriptTask's 'executable' is required.");
210         }
211         if (mIncludePath == null) {
212             throw new BuildException("RenderScriptTask's 'includePath' is required.");
213         }
214         if (mGenFolder == null) {
215             throw new BuildException("RenderScriptTask's 'genFolder' is required.");
216         }
217         if (mResFolder == null) {
218             throw new BuildException("RenderScriptTask's 'resFolder' is required.");
219         }
220         if (mTargetApi == 0) {
221             throw new BuildException("RenderScriptTask's 'targetApi' is required.");
222         }
223 
224         processFiles(new RenderScriptProcessor(mTargetApi), mPaths, mGenFolder);
225     }
226 }
227