Home | History | Annotate | Download | only in build
      1 /*
      2 * Copyright 2013 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 // The SampleGenPlugin source is in the buildSrc directory.
     18 import com.example.android.samples.build.SampleGenPlugin
     19 apply plugin: SampleGenPlugin
     20 
     21 // Add a preflight task that depends on the "refresh" task that gets
     22 // added by the SampleGenPlugin.
     23 task preflight {
     24     project.afterEvaluate({preflight.dependsOn(project.refresh)})
     25 }
     26 
     27 task wrapper(type: Wrapper) {
     28     gradleVersion = '2.10'
     29 }
     30 
     31 
     32 String outPath(String buildType) {
     33 /*
     34     def repoInfo = "repo info platform/developers/build".execute().text
     35     def buildPath = (repoInfo =~ /Mount path: (.*)/)[0][1]
     36 */
     37     return "${samplegen.pathToBuild}/out/${buildType}/${samplegen.targetSampleName()}";
     38 }
     39 
     40 /**
     41  * Collapse a path "IntelliJ-style" by putting dots rather than slashes between
     42  * path components that have only one child. So the two paths
     43  *
     44  * com/example/android/foo/bar.java
     45  * com/example/android/bar/foo.java
     46  *
     47  * Become
     48  * com.example.android/foo/bar.java
     49  * com.example.android/bar/foo.java
     50  *
     51  * @param path
     52  * @param roots
     53  * @return
     54  */
     55 Map<String,String> collapsePaths(FileTree path, List<String> roots) {
     56     Map result = new HashMap<String,String>();
     57 
     58     println ("******************** Collapse *************************")
     59 
     60     path.visit { FileVisitDetails f ->
     61         if (f.isDirectory()) return;
     62         StringBuilder collapsedPath = new StringBuilder("${f.name}");
     63         File current = f.file;
     64 
     65         //
     66         // Starting at this file, walk back to the root of the path and
     67         // substitute dots for any directory that has only one child.
     68         //
     69 
     70         // Don't substitute a dot for the separator between the end of the
     71         // path and the filename, even if there's only one file in the directory.
     72         if (!f.isDirectory()) {
     73             current = current.parentFile;
     74             collapsedPath.insert(0, "${current.name}/")
     75         }
     76 
     77         // For everything else, use a dot if there's only one child and
     78         // a slash otherwise. Filter out the root paths, too--we only want
     79         // the relative path. But wait, Groovy/Gradle is capricious and
     80         // won't return the proper value from a call to roots.contains(String)!
     81         // I'm using roots.sum here instead of tracking down why a list of
     82         // strings can't return true from contains() when given a string that
     83         // it quite obviously does contain.
     84         current = current.parentFile;
     85         while((current != null)
     86                 && (roots.sum {String r-> return r.equals(current.absolutePath) ? 1 : 0 } == 0)) {
     87 
     88             char separator = current.list().length > 1 ? '/' : '.';
     89             collapsedPath.insert(0, "${current.name}${separator}");
     90             current = current.parentFile;
     91         }
     92         result.put(f.file.path, collapsedPath.toString());
     93     }
     94 
     95     println ("******************** Collapse results *********************")
     96 
     97     result.each {entry -> println("- ${entry}");}
     98     return result
     99 }
    100 
    101 
    102 task emitAnt(type:Copy) {
    103     def outputPath = outPath("ant");
    104     def inputPath = "${project.projectDir}/${samplegen.targetSampleModule()}"
    105     into outputPath
    106     includeEmptyDirs
    107     ["main", "common", "template"].each { input ->
    108         [[ "java", "src"], ["res", "res"]].each { filetype ->
    109             def srcPath = "${inputPath}/src/${input}/${filetype[0]}"
    110             into("${filetype[1]}") {
    111                 from(srcPath)
    112             }
    113         }
    114     }
    115     from("${inputPath}/src/main") { include "AndroidManifest.xml" }
    116     from("${inputPath}/src/template") { include "project.properties" }
    117 }
    118 
    119 task emitGradle(type:Copy) {
    120     dependsOn(preflight)
    121     def outputPath = outPath("gradle")
    122     def inputPath = "${project.projectDir}"
    123     // Copy entire sample into output -- since it's already in Gradle format, we'll explicitly exclude content that
    124     // doesn't belong here.
    125     into outputPath
    126     from("${inputPath}") {
    127         // Paths to exclude from output
    128         exclude ".gradle"
    129         exclude "_index.jd"
    130         exclude "bin"
    131         exclude "buildSrc"
    132         exclude "local.properties"
    133         exclude "template-params.xml"
    134         exclude "*.iml"
    135         exclude "**/.idea"
    136         exclude "**/build"
    137         exclude "**/proguard-project.txt"
    138         exclude "${samplegen.targetSampleModule()}/**/README*.txt"
    139         exclude "**/README-*.txt"
    140 
    141         // src directory needs to be consolidated, will be done in next section
    142         exclude "${samplegen.targetSampleModule()}/src/"
    143     }
    144 
    145     // Consolidate source directories
    146     ["main", "common", "template"].each { input ->
    147         ["java", "res", "assets", "rs"].each { filetype ->
    148             def srcPath = "${inputPath}/${samplegen.targetSampleModule()}/src/${input}/${filetype}"
    149             into("${samplegen.targetSampleModule()}/src/main/${filetype}") {
    150                 from(srcPath)
    151             }
    152         }
    153     }
    154 
    155     // Copy AndroidManifest.xml
    156     into ("${samplegen.targetSampleModule()}/src/main") {
    157         from("${inputPath}/${samplegen.targetSampleModule()}/src/main/AndroidManifest.xml")
    158     }
    159 
    160     // Remove BEGIN_EXCLUDE/END_EXCLUDE blocks from source files
    161     eachFile { file ->
    162         if (file.name.endsWith(".gradle") || file.name.endsWith(".java")) {
    163             // TODO(trevorjohns): Outputs a blank newline for each filtered line. Replace with java.io.FilterReader impl.
    164             boolean outputLines = true;
    165             def removeExcludeBlocksFilter = { line ->
    166                 if (line ==~ /\/\/ BEGIN_EXCLUDE/) {
    167                     outputLines = false;
    168                 } else if (line ==~ /\/\/ END_EXCLUDE/) {
    169                     outputLines = true;
    170                 } else if (outputLines) {
    171                     return line;
    172                 }
    173                 return ""
    174             }
    175             filter(removeExcludeBlocksFilter)
    176         }
    177     }
    178 }
    179 
    180 task emitBrowseable(type:Copy) {
    181     def outputPathRoot = outPath("browseable")
    182     def modules = project.childProjects.keySet()
    183     def hasMultipleModules = modules.size() > 1
    184     println "---------------- modules found in sample: ${modules}"
    185     into outputPathRoot
    186     from("${project.projectDir}/_index.jd")
    187 
    188     modules.each { moduleName ->
    189         // For single module samples (default), we emit the module contents
    190         // directly to the root of the browseable sample:
    191         def outputPath = "."
    192         if (hasMultipleModules) {
    193           // For multi module samples, we need an extra directory level
    194           // to separate modules:
    195           outputPath = "${moduleName}"
    196         }
    197         println "\n---------------- processing MODULE ${moduleName} to outputPath ${outputPath}"
    198         def inputPath = "${project.projectDir}/${moduleName}"
    199 
    200         def srcDirs = ["main", "common", "template"].collect {input -> "${inputPath}/src/${input}" };
    201         def javaDirs = srcDirs.collect { input -> "${input}/java"}
    202         FileTree javaTree = null;
    203         javaDirs.each { dir ->
    204             FileTree tree = project.fileTree("${dir}")
    205             javaTree = (javaTree == null) ? tree : javaTree.plus(tree)}
    206         Map collapsedPaths = collapsePaths(javaTree, javaDirs)
    207 
    208         srcDirs.each { srcPath ->
    209             print "** Copying source ${srcPath}...";
    210             duplicatesStrategy = 'fail'
    211             into("${outputPath}/src") {
    212                 def javaPath = "${srcPath}/java";
    213                 from(javaPath)
    214                 include(["**/*.java", "**/*.xml"])
    215                 eachFile { FileCopyDetails fcd ->
    216                     if (fcd.file.isFile()) {
    217                         def filename = fcd.name;
    218                         String collapsed = collapsedPaths.get(fcd.file.path);
    219                         fcd.path = "${outputPath}/src/${collapsed}";
    220                     } else {fcd.exclude()}
    221                 }
    222                 println "done"
    223             }
    224             into("${outputPath}/res") {
    225                 from("${srcPath}/res")
    226             }
    227             into("${outputPath}/src/rs") {
    228                 from("${srcPath}/rs")
    229             }
    230             into("${outputPath}") {from("${srcPath}/AndroidManifest.xml")}
    231         }
    232     }
    233 }
    234 
    235 task emitGradleZip(dependsOn: [emitBrowseable, emitGradle], type:Zip) {
    236     def outputPath = "${samplegen.pathToBuild}/out/browseable"
    237     def folderName = "${samplegen.targetSampleName()}"
    238     archiveName = "${samplegen.targetSampleName()}.zip"
    239     def inputPath = outPath("gradle")
    240     from inputPath
    241     into folderName
    242     include "**"
    243     def outDir = project.file(outputPath)
    244     destinationDir = outDir
    245 }
    246