• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.PrintStream;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Set;
27 
28 /**
29  * A base class for ant tasks that use a single dependency file to control (re)execution.
30  */
31 public abstract class SingleDependencyTask extends BuildTypedTask {
32 
33     private DependencyGraph mDependencies;
34 
getExecTaskName()35     protected abstract String getExecTaskName();
36 
37     protected interface InputPathFactory {
createPath(File file, Set<String> extensionsToCheck)38         InputPath createPath(File file, Set<String> extensionsToCheck);
39     }
40 
41     private final static InputPathFactory sDefaultFactory = new InputPathFactory() {
42         @Override
43         public InputPath createPath(File file, Set<String> extensionsToCheck) {
44             return new InputPath(file, extensionsToCheck);
45         }
46     };
47 
48     /**
49      * Creates a list of {@link InputPath} from a list of {@link File} and an optional list of
50      * extensions. All the {@link InputPath} will share the same extension restrictions.
51      * @param paths the list of path
52      * @param extensionsToCheck A set of extensions. Only files with an extension in this set will
53      *             be considered for a modification check. All deleted/created files will still be
54      *             checked. If this is null, all files will be checked for modification date
55      * @return a list of {@link InputPath}
56      */
getInputPaths(List<File> paths, Set<String> extensionsToCheck, InputPathFactory factory)57     protected static List<InputPath> getInputPaths(List<File> paths,
58             Set<String> extensionsToCheck, InputPathFactory factory) {
59         List<InputPath> result = new ArrayList<InputPath>(paths.size());
60 
61         if (factory == null ) {
62             factory = sDefaultFactory;
63         }
64 
65         for (File f : paths) {
66             result.add(factory.createPath(f, extensionsToCheck));
67         }
68 
69         return result;
70     }
71 
72     /**
73      * Set up the dependency graph by passing it the location of the ".d" file, and the new input
74      * paths.
75      * @param dependencyFile path to the dependency file to use
76      * @param the new input paths for this new compilation.
77      * @return true if the dependency graph was successfully initialized
78      */
initDependencies(String dependencyFile, List<InputPath> inputPaths)79     protected boolean initDependencies(String dependencyFile, List<InputPath> inputPaths) {
80         if (hasBuildTypeChanged()) {
81             // we don't care about deps, we need to execute the task no matter what.
82             return true;
83         }
84 
85         File depFile = new File(dependencyFile);
86         if (depFile.exists()) {
87             mDependencies = new DependencyGraph(dependencyFile, inputPaths);
88             return true;
89         } else {
90             return false;
91         }
92     }
93 
94     /**
95      * Wrapper check to see if we need to execute this task at all
96      * @return true if the DependencyGraph reports that our prereqs or targets
97      *         have changed since the last run
98      */
dependenciesHaveChanged()99     protected boolean dependenciesHaveChanged() {
100         if (hasBuildTypeChanged()) {
101             // if this is not a new build, display that build type change is forcing running
102             // the task.
103             if (isNewBuild() == false) {
104                 String execName = getExecTaskName();
105                 if (execName == null) {
106                     System.out.println(
107                             "Current build type is different than previous build: forced task run.");
108                 } else {
109                     System.out.println(
110                             "Current build type is different than previous build: forced " +
111                             execName + " run.");
112                 }
113             }
114             return true;
115         }
116 
117         assert mDependencies != null : "Dependencies have not been initialized";
118         return mDependencies.dependenciesHaveChanged(true /*printStatus*/);
119     }
120 
generateDependencyFile(String depFilePath, List<InputPath> inputs, String outputFile)121     protected void generateDependencyFile(String depFilePath,
122             List<InputPath> inputs, String outputFile) {
123         File depFile = new File(depFilePath);
124 
125         try {
126             PrintStream ps = new PrintStream(depFile);
127 
128             // write the output file.
129             ps.print(outputFile);
130             ps.println(" : \\");
131 
132             //write the input files
133             int count = inputs.size();
134             for (int i = 0 ; i < count ; i++) {
135                 InputPath input = inputs.get(i);
136                 File file = input.getFile();
137                 if (file.isDirectory()) {
138                     writeContent(ps, file, input);
139                 } else {
140                     ps.print(file.getAbsolutePath());
141                     ps.println(" \\");
142                 }
143             }
144 
145             ps.close();
146         } catch (FileNotFoundException e) {
147             new BuildException(e);
148         }
149     }
150 
writeContent(PrintStream ps, File file, InputPath input)151     private void writeContent(PrintStream ps, File file, InputPath input) {
152         if (input.ignores(file)) {
153             return;
154         }
155 
156         File[] files = file.listFiles();
157         if (files != null) {
158             for (File f : files) {
159                 if (f.isDirectory()) {
160                     writeContent(ps, f, input);
161                 } else if (input.ignores(f) == false) {
162                     ps.print(f.getAbsolutePath());
163                     ps.println(" \\");
164                 }
165             }
166         }
167     }
168 }
169