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. 18import com.example.android.samples.build.SampleGenPlugin 19apply plugin: SampleGenPlugin 20 21// Add a preflight task that depends on the "refresh" task that gets 22// added by the SampleGenPlugin. 23task preflight { 24 project.afterEvaluate({preflight.dependsOn(project.refresh)}) 25} 26 27task wrapper(type: Wrapper) { 28 gradleVersion = '1.8' 29} 30 31 32String 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 */ 55Map<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 102task 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 119task 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 140 // src directory needs to be consolidated, will be done in next section 141 exclude "${samplegen.targetSampleModule()}/src/" 142 } 143 144 // Consolidate source directories 145 ["main", "common", "template"].each { input -> 146 ["java", "res", "assets", "rs"].each { filetype -> 147 def srcPath = "${inputPath}/${samplegen.targetSampleModule()}/src/${input}/${filetype}" 148 into("${samplegen.targetSampleModule()}/src/main/${filetype}") { 149 from(srcPath) 150 } 151 } 152 } 153 154 // Copy AndroidManifest.xml 155 into ("${samplegen.targetSampleModule()}/src/main") { 156 from("${inputPath}/${samplegen.targetSampleModule()}/src/main/AndroidManifest.xml") 157 } 158 159 // Remove BEGIN_EXCLUDE/END_EXCLUDE blocks from source files 160 eachFile { file -> 161 if (file.name.endsWith(".gradle") || file.name.endsWith(".java")) { 162 // TODO(trevorjohns): Outputs a blank newline for each filtered line. Replace with java.io.FilterReader impl. 163 boolean outputLines = true; 164 def removeExcludeBlocksFilter = { line -> 165 if (line ==~ /\/\/ BEGIN_EXCLUDE/) { 166 outputLines = false; 167 } else if (line ==~ /\/\/ END_EXCLUDE/) { 168 outputLines = true; 169 } else if (outputLines) { 170 return line; 171 } 172 return "" 173 } 174 filter(removeExcludeBlocksFilter) 175 } 176 } 177} 178 179task emitBrowseable(type:Copy) { 180 def outputPathRoot = outPath("browseable") 181 def modules = project.childProjects.keySet() 182 def hasMultipleModules = modules.size() > 1 183 println "---------------- modules found in sample: ${modules}" 184 into outputPathRoot 185 from("${project.projectDir}/_index.jd") 186 187 modules.each { moduleName -> 188 // For single module samples (default), we emit the module contents 189 // directly to the root of the browseable sample: 190 def outputPath = "." 191 if (hasMultipleModules) { 192 // For multi module samples, we need an extra directory level 193 // to separate modules: 194 outputPath = "${moduleName}" 195 } 196 println "\n---------------- processing MODULE ${moduleName} to outputPath ${outputPath}" 197 def inputPath = "${project.projectDir}/${moduleName}" 198 199 def srcDirs = ["main", "common", "template"].collect {input -> "${inputPath}/src/${input}" }; 200 def javaDirs = srcDirs.collect { input -> "${input}/java"} 201 FileTree javaTree = null; 202 javaDirs.each { dir -> 203 FileTree tree = project.fileTree("${dir}") 204 javaTree = (javaTree == null) ? tree : javaTree.plus(tree)} 205 Map collapsedPaths = collapsePaths(javaTree, javaDirs) 206 207 srcDirs.each { srcPath -> 208 print "** Copying source ${srcPath}..."; 209 duplicatesStrategy = 'fail' 210 into("${outputPath}/src") { 211 def javaPath = "${srcPath}/java"; 212 from(javaPath) 213 include(["**/*.java", "**/*.xml"]) 214 eachFile { FileCopyDetails fcd -> 215 if (fcd.file.isFile()) { 216 def filename = fcd.name; 217 String collapsed = collapsedPaths.get(fcd.file.path); 218 fcd.path = "${outputPath}/src/${collapsed}"; 219 } else {fcd.exclude()} 220 } 221 println "done" 222 } 223 into("${outputPath}/res") { 224 from("${srcPath}/res") 225 } 226 into("${outputPath}/src/rs") { 227 from("${srcPath}/rs") 228 } 229 into("${outputPath}") {from("${srcPath}/AndroidManifest.xml")} 230 } 231 } 232} 233 234task emitGradleZip(dependsOn: [emitBrowseable, emitGradle], type:Zip) { 235 def outputPath = "${samplegen.pathToBuild}/out/browseable" 236 def folderName = "${samplegen.targetSampleName()}" 237 archiveName = "${samplegen.targetSampleName()}.zip" 238 def inputPath = outPath("gradle") 239 from inputPath 240 into folderName 241 include "**" 242 def outDir = project.file(outputPath) 243 destinationDir = outDir 244} 245