• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 com.android.ant.DependencyHelper.LibraryProcessorFor3rdPartyJars;
20 import com.android.io.FileWrapper;
21 import com.android.sdklib.SdkConstants;
22 import com.android.sdklib.internal.project.IPropertySource;
23 import com.android.sdklib.xml.AndroidManifest;
24 
25 import org.apache.tools.ant.BuildException;
26 import org.apache.tools.ant.Project;
27 import org.apache.tools.ant.types.Path;
28 import org.apache.tools.ant.types.Path.PathElement;
29 
30 import java.io.File;
31 import java.util.List;
32 
33 /**
34  * Computes the dependency of the current project.
35  *
36  * Out params:
37  * <code>libraryResFolderPathOut</code>: the Path object containing the res folder for all the
38  * library projects in the order needed by aapt.
39  *
40  * <code>libraryPackagesOut</code>: a simple property containing ;-separated package name from
41  * the library projects.
42  *
43  * <code>jarLibraryPathOut</code>: the Path object containing all the 3rd party jar files.
44  *
45  * <code>libraryNativeFolderPathOut</code>: the Path with all the native folder for the library
46  * projects.
47  *
48  *
49  * In params:
50  * <code>targetApi</code>: the compilation target api.
51  * <code>verbose</code>: whether the build is verbose.
52  *
53  */
54 public class ComputeDependencyTask extends GetLibraryListTask {
55 
56     private String mLibraryManifestFilePathOut;
57     private String mLibraryResFolderPathOut;
58     private String mLibraryPackagesOut;
59     private String mJarLibraryPathOut;
60     private String mLibraryNativeFolderPathOut;
61     private int mTargetApi = -1;
62     private boolean mVerbose = false;
63 
setLibraryManifestFilePathOut(String libraryManifestFilePathOut)64     public void setLibraryManifestFilePathOut(String libraryManifestFilePathOut) {
65         mLibraryManifestFilePathOut = libraryManifestFilePathOut;
66     }
67 
setLibraryResFolderPathOut(String libraryResFolderPathOut)68     public void setLibraryResFolderPathOut(String libraryResFolderPathOut) {
69         mLibraryResFolderPathOut = libraryResFolderPathOut;
70     }
71 
setLibraryPackagesOut(String libraryPackagesOut)72     public void setLibraryPackagesOut(String libraryPackagesOut) {
73         mLibraryPackagesOut = libraryPackagesOut;
74     }
75 
setJarLibraryPathOut(String jarLibraryPathOut)76     public void setJarLibraryPathOut(String jarLibraryPathOut) {
77         mJarLibraryPathOut = jarLibraryPathOut;
78     }
79 
setLibraryNativeFolderPathOut(String libraryNativeFolderPathOut)80     public void setLibraryNativeFolderPathOut(String libraryNativeFolderPathOut) {
81         mLibraryNativeFolderPathOut = libraryNativeFolderPathOut;
82     }
83 
setTargetApi(int targetApi)84     public void setTargetApi(int targetApi) {
85         mTargetApi = targetApi;
86     }
87 
88     /**
89      * Sets the value of the "verbose" attribute.
90      * @param verbose the value.
91      */
setVerbose(boolean verbose)92     public void setVerbose(boolean verbose) {
93         mVerbose = verbose;
94     }
95 
96     @Override
execute()97     public void execute() throws BuildException {
98         if (mLibraryManifestFilePathOut == null) {
99             throw new BuildException("Missing attribute libraryManifestFilePathOut");
100         }
101         if (mLibraryResFolderPathOut == null) {
102             throw new BuildException("Missing attribute libraryResFolderPathOut");
103         }
104         if (mLibraryPackagesOut == null) {
105             throw new BuildException("Missing attribute libraryPackagesOut");
106         }
107         if (mJarLibraryPathOut == null) {
108             throw new BuildException("Missing attribute jarLibraryPathOut");
109         }
110         if (mLibraryNativeFolderPathOut == null) {
111             throw new BuildException("Missing attribute libraryNativeFolderPathOut");
112         }
113         if (mTargetApi == -1) {
114             throw new BuildException("Missing attribute targetApi");
115         }
116 
117         final Project antProject = getProject();
118 
119         // get the SDK location
120         File sdkDir = TaskHelper.getSdkLocation(antProject);
121 
122         // prepare several paths for future tasks
123         final Path manifestFilePath = new Path(antProject);
124         final Path resFolderPath = new Path(antProject);
125         final Path nativeFolderPath = new Path(antProject);
126         final StringBuilder packageStrBuilder = new StringBuilder();
127 
128         LibraryProcessorFor3rdPartyJars processor = new LibraryProcessorFor3rdPartyJars() {
129             @Override
130             public void processLibrary(String libRootPath) {
131                 // let the super class handle the jar files
132                 super.processLibrary(libRootPath);
133 
134                 // get the AndroidManifest.xml path.
135                 // FIXME: support renamed location.
136                 PathElement element = manifestFilePath.createPathElement();
137                 element.setPath(libRootPath + "/" + SdkConstants.FN_ANDROID_MANIFEST_XML);
138 
139                 // get the res path. $PROJECT/res as well as the crunch cache.
140                 // FIXME: support renamed folders.
141                 element = resFolderPath.createPathElement();
142                 element.setPath(libRootPath + "/" + SdkConstants.FD_OUTPUT +
143                         "/" + SdkConstants.FD_RES);
144                 element = resFolderPath.createPathElement();
145                 element.setPath(libRootPath + "/" + SdkConstants.FD_RESOURCES);
146 
147 
148                 // get the folder for the native libraries. Always $PROJECT/libs
149                 // FIXME: support renamed folder.
150                 element = nativeFolderPath.createPathElement();
151                 element.setPath(libRootPath + "/" + SdkConstants.FD_NATIVE_LIBS);
152 
153                 // get the package from the manifest.
154                 FileWrapper manifest = new FileWrapper(libRootPath,
155                         SdkConstants.FN_ANDROID_MANIFEST_XML);
156 
157                 try {
158                     String value = AndroidManifest.getPackage(manifest);
159                     if (value != null) { // aapt will complain if it's missing.
160                         packageStrBuilder.append(';');
161                         packageStrBuilder.append(value);
162                     }
163                 } catch (Exception e) {
164                     throw new BuildException(e);
165                 }
166             }
167         };
168 
169         // list of all the jars that are on the classpath. This will receive the
170         // project's libs/*.jar files, the Library Projects output and their own libs/*.jar
171         List<File> jars = processor.getJars();
172 
173 
174         // in case clean has been called before a build type target, the list of
175         // libraries has already been computed so we don't need to compute it again.
176         Path libraryFolderPath = (Path) antProject.getReference(getLibraryFolderPathOut());
177         if (libraryFolderPath == null) {
178             execute(processor);
179         } else {
180             // this contains the list of library folder in reverse order (compilation order).
181             // We need to process it in the normal order (res order).
182             System.out.println("Ordered libraries:");
183 
184             String[] libraries = libraryFolderPath.list();
185             for (int i = libraries.length - 1 ; i >= 0 ; i--) {
186                 String libRootPath = libraries[i];
187                 System.out.println(libRootPath);
188 
189                 processor.processLibrary(libRootPath);
190             }
191         }
192 
193         boolean hasLibraries = jars.size() > 0;
194 
195         if (mTargetApi <= 15) {
196             System.out.println("\n------------------");
197             System.out.println("API<=15: Adding annotations.jar to the classpath.");
198 
199             jars.add(new File(sdkDir, SdkConstants.FD_TOOLS +
200                     "/" + SdkConstants.FD_SUPPORT +
201                     "/" + SdkConstants.FN_ANNOTATIONS_JAR));
202 
203         }
204 
205         // even with no libraries, always setup these so that various tasks in Ant don't complain
206         // (the task themselves can handle a ref to an empty Path)
207         antProject.addReference(mLibraryNativeFolderPathOut, nativeFolderPath);
208         antProject.addReference(mLibraryManifestFilePathOut, manifestFilePath);
209 
210         // the rest is done only if there's a library.
211         if (hasLibraries) {
212             antProject.addReference(mLibraryResFolderPathOut, resFolderPath);
213             antProject.setProperty(mLibraryPackagesOut, packageStrBuilder.toString());
214         }
215 
216         File projectFolder = antProject.getBaseDir();
217 
218         // add the project's own content of libs/*.jar
219         File libsFolder = new File(projectFolder, SdkConstants.FD_NATIVE_LIBS);
220         File[] jarFiles = libsFolder.listFiles(processor.getFilter());
221         if (jarFiles != null) {
222             for (File jarFile : jarFiles) {
223                 jars.add(jarFile);
224             }
225         }
226 
227         // now sanitize the path to remove dups
228         jars = DependencyHelper.sanitizePaths(projectFolder, new IPropertySource() {
229             @Override
230             public String getProperty(String name) {
231                 return antProject.getProperty(name);
232             }
233         }, jars);
234 
235         // and create a Path object for them
236         Path jarsPath = new Path(antProject);
237         if (mVerbose) {
238             System.out.println("\n------------------\nSanitized jar list:");
239         }
240         for (File f : jars) {
241             if (mVerbose) {
242                 System.out.println("- " + f.getAbsolutePath());
243             }
244             PathElement element = jarsPath.createPathElement();
245             element.setPath(f.getAbsolutePath());
246         }
247         antProject.addReference(mJarLibraryPathOut, jarsPath);
248 
249         if (mVerbose) {
250             System.out.println();
251         }
252 
253     }
254 }
255