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