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