From 52b3d0f78cad256a83dd924edd21f835074a3532 Mon Sep 17 00:00:00 2001 From: blagoev Date: Tue, 12 Apr 2016 23:05:39 +0300 Subject: [PATCH 1/7] fixes #369 long paths on window A possible temporary fix for the long paths on Windows builds when multiple {N} plugins are used. --- build/project-template-gradle/build.gradle | 134 ++++++++++----------- 1 file changed, 61 insertions(+), 73 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index 19fb432f6..0c7af44e8 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -15,7 +15,7 @@ * -PsupportVersion=[support_version] (default (22.2.0) * -PcompileSdk=[compile_sdk_version] (default 22) * -* -PdontRunSbg=[true/false] (default false) +* -PrunSBGenerator //this flag will triger static binding generation */ buildscript { @@ -33,19 +33,15 @@ apply plugin: "com.android.application" def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') def metadataParams = new LinkedList () def allJarPaths = new LinkedList () -def configurationsDir = "$projectDir/configurations" +def configurationsDir = "configurations" def createPluginConfigFile = false def configStage = "\n:config phase: " def nodeModulesDir = "../../node_modules/" -def libDir = "$projectDir/../../lib/Android/" +def libDir = "../../lib/Android/" def pluginNames = new ArrayList() def configDir = file(configurationsDir) - -def dontRunSbg = project.hasProperty("dontRunSbg"); - -def asbgProject = project(":asbg") -asbgProject.ext.outDir = new File("$projectDir", "src/main/java") -asbgProject.ext.jsCodeDir = new File("$projectDir", "src/main/assets/app") +def appResExists = false +def appResourcesName = "NativescriptAppResources" def compiteCompileSdkVersion () { if(project.hasProperty("compileSdk")) { @@ -70,7 +66,7 @@ def computeBuildToolsVersion() { return buildToolsVersion } else { - return "23.0.1" + return "22.0.1" } } project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug" @@ -106,7 +102,7 @@ android { } sourceSets.main { - jniLibs.srcDir "$projectDir/libs/jni" + jniLibs.srcDir "libs/jni" } signingConfigs { @@ -140,15 +136,7 @@ android { def variantName = variant.name.capitalize() def compileSourcesTaskName = "compile${variantName}Sources" def compileSourcesTask = project.tasks.findByName(compileSourcesTaskName) - - def generateBuildConfigTask = variant.generateBuildConfig; - generateBuildConfigTask.finalizedBy(collectAllJars) - - if(!dontRunSbg) { - collectAllJars.finalizedBy(setProperties) - } - - compileSourcesTask.finalizedBy(buildMetadata) + compileSourcesTask.finalizedBy "buildMetadata" } } @@ -170,7 +158,7 @@ dependencies { compile "com.android.support:appcompat-v7:$suppotVer" // take all jars within the libs dir - compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"]) + compile fileTree(dir: "libs", include: ["**/*.jar"]) // take all jars within the node_modules dir compile fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.jar"], exclude: '**/.bin/**') @@ -206,8 +194,9 @@ task pluginStructureCheck { } } + def createIncludeFile (filePath, fileName, dimensionName) { - println "\t+creating include.gradle file for: " + filePath + println "\t+creating include.gradle file for: " + filePath + " flavor: " + fileName def defaultIncludeFile = new File(filePath, "include.gradle") defaultIncludeFile.write "" defaultIncludeFile << "android { \n" @@ -224,18 +213,27 @@ def sanatizeDimensionName(str) { } //make sure the include.gradle file, produced by the user, has only allowed characters in dimension attribute and remove any invalid characters if necessary -def updateIncludeGradleFile(subFile, dimensionName) { +def updateIncludeGradleFile(subFile, dimensionName, flavor) { def igFile = new File(subFile.getAbsolutePath()) def newContent = igFile.text.replaceAll(/dimension\s+["'](.+?)["']/) { fullMatch, fDimension -> def newFg = sanatizeDimensionName(fDimension) dimensionName = newFg return "dimension \"$newFg\"" } - igFile.text = newContent + + //println "Before patch: " + newContent + + def finalContent = newContent.replace(dimensionName + "\" {", flavor + "\" {") + + //println "Dimension: " + dimensionName + " final content: " + finalContent + + igFile.text = finalContent return dimensionName } +def flavorNumber = 0 + task createDefaultIncludeFiles { description "creates default include.gradle files for added plugins IF NECESSARY" println "$configStage createDefaultIncludeFiles" @@ -249,19 +247,22 @@ task createDefaultIncludeFiles { createPluginConfigFile = true def foundIncludeFile = false + def flavor = "F" + flavorNumber++ + println "\t+found plugins: " + fileName fl.listFiles().each { subFile -> if(subFile.name == "include.gradle") { foundIncludeFile = true - dimensionName = updateIncludeGradleFile(subFile, dimensionName) + dimensionName = updateIncludeGradleFile(subFile, dimensionName, flavor) } } pluginNames.add('"' + dimensionName + '"') if(!foundIncludeFile) { - createIncludeFile(fl.getAbsolutePath() ,fileName, dimensionName) + //createIncludeFile(fl.getAbsolutePath(), fileName, dimensionName) + createIncludeFile(fl.getAbsolutePath() , flavor, dimensionName) } } } @@ -290,7 +291,7 @@ task createPluginsConfigFile { task pluginExtend { description "applies additional configuration" - def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle" + def pathToAppGradle = "../../app/App_Resources/Android/app.gradle" def appGradle = file(pathToAppGradle) if(appGradle.exists()) { apply from: pathToAppGradle @@ -322,13 +323,13 @@ task pluginExtend { task copyAarDependencies (type: Copy) { println "$configStage copyAarDependencies" from fileTree(dir: nodeModulesDir, include: ["**/*.aar"], exclude: '**/.bin/**').files - into "$projectDir/libs/aar" + into "libs/aar" } task addAarDependencies << { println "$configStage addAarDependencies" // manually traverse all the locally copied AAR files and add them to the project compilation dependencies list - FileTree tree = fileTree(dir: "$projectDir/libs/aar", include: ["**/*.aar"]) + FileTree tree = fileTree(dir: "libs/aar", include: ["**/*.aar"]) tree.each { File file -> // remove the extension of the file (.aar) def length = file.name.length() - 4 @@ -344,11 +345,11 @@ task addAarDependencies << { //////////////////////////////////////////////////////////////////////////////////// task cleanLocalAarFiles(type: Delete) { - delete fileTree(dir: "$projectDir/libs/aar", include: ["*.aar"]) + delete fileTree(dir: "libs/aar", include: ["*.aar"]) } task ensureMetadataOutDir { - def outputDir = file("$projectDir/metadata/output/assets/metadata") + def outputDir = file("$rootDir/metadata/output/assets/metadata") outputDir.mkdirs() } @@ -373,35 +374,12 @@ task collectAllJars { } metadataParams.add("metadata-generator.jar") - metadataParams.add("$projectDir/metadata/output/assets/metadata") - def jars = new LinkedList() + metadataParams.add("../metadata/output/assets/metadata") for(def i = 0; i < allJarPaths.size(); i++) { metadataParams.add(allJarPaths.get(i)); - def f = new File(allJarPaths.get(i)) - if (f.getName().endsWith(".jar")) { - jars.add(f) - } } - asbgProject.ext.jarFiles = jars - } -} -task buildMetadata (type: JavaExec) { - description "builds metadata with provided jar dependencies" - - inputs.files(allJarPaths) - inputs.dir("$buildDir/intermediates/classes") - - outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat") - - doFirst { - workingDir "build-tools" - - main "-jar" - - // get compiled classes to pass to metadata generator - // these need to be called after the classes have compiled - def classesDir = "$buildDir/intermediates/classes" + def classesDir = "$rootDir/build/intermediates/classes" def classesSubDirs = new File(classesDir).listFiles() @@ -420,14 +398,30 @@ task buildMetadata (type: JavaExec) { if (classesDirBuildType.exists()) { metadataParams.add(classesDirBuildType.getAbsolutePath()) } + } +} + + +task buildMetadata (type: JavaExec) { + description "builds metadata with provided jar dependencies" + + inputs.files(allJarPaths) + inputs.dir("build/intermediates/classes") + + outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat") + + doFirst { + workingDir "build-tools" + + main "-jar" args metadataParams.toArray() } doLast { copy { - from "$projectDir/metadata/output/assets/metadata" - into "$projectDir/src/main/assets/metadata" + from "metadata/output/assets/metadata" + into "src/main/assets/metadata" } def files = new File("${buildDir}/intermediates/res").listFiles() @@ -451,14 +445,14 @@ task buildMetadata (type: JavaExec) { exec { ignoreExitValue true - workingDir "$projectDir/metadata/output" + workingDir "metadata/output" commandLine removeCmdParams.toArray() } def addCmdParams = new ArrayList([aaptCommand, "add", tmpAPKPath, "assets/metadata/treeNodeStream.dat", "assets/metadata/treeStringsStream.dat", "assets/metadata/treeValueStream.dat"]) exec { - workingDir "$projectDir/metadata/output" + workingDir "metadata/output" commandLine addCmdParams.toArray() } } @@ -480,20 +474,14 @@ task deleteExplodedAarFolder (type: Delete) { //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// OPTIONAL TASKS ////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// -task setProperties { - project.ext.jarFiles = [] - doLast { - def list = []; - allJarPaths.each({f -> - if(f.endsWith(".jar")) { - list.add(f); - } - }) - project.jarFiles = list; - } -} +task runBindingGenerator(dependsOn: "ing:jar") { + rootProject.jarsDir = allJarPaths +} +runBindingGenerator.dependsOn("bg:jar") + +task rbg (dependsOn: "asbg:generatebindings") + -setProperties.finalizedBy("asbg:generateBindings") //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// EXECUTION ORDER ///////////////////////////////////// From 8fbe7614061ac882ee9160a7a6c87d2927706821 Mon Sep 17 00:00:00 2001 From: blagoev Date: Tue, 12 Apr 2016 23:09:35 +0300 Subject: [PATCH 2/7] use the correct build.gradle file --- build/project-template-gradle/build.gradle | 123 ++++++++++++--------- 1 file changed, 73 insertions(+), 50 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index 0c7af44e8..ac8ca5f64 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -15,7 +15,7 @@ * -PsupportVersion=[support_version] (default (22.2.0) * -PcompileSdk=[compile_sdk_version] (default 22) * -* -PrunSBGenerator //this flag will triger static binding generation +* -PdontRunSbg=[true/false] (default false) */ buildscript { @@ -33,15 +33,19 @@ apply plugin: "com.android.application" def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') def metadataParams = new LinkedList () def allJarPaths = new LinkedList () -def configurationsDir = "configurations" +def configurationsDir = "$projectDir/configurations" def createPluginConfigFile = false def configStage = "\n:config phase: " def nodeModulesDir = "../../node_modules/" -def libDir = "../../lib/Android/" -def pluginNames = new ArrayList() +def libDir = "$projectDir/../../lib/Android/" +def flavorNames = new ArrayList() def configDir = file(configurationsDir) -def appResExists = false -def appResourcesName = "NativescriptAppResources" + +def dontRunSbg = project.hasProperty("dontRunSbg"); + +def asbgProject = project(":asbg") +asbgProject.ext.outDir = new File("$projectDir", "src/main/java") +asbgProject.ext.jsCodeDir = new File("$projectDir", "src/main/assets/app") def compiteCompileSdkVersion () { if(project.hasProperty("compileSdk")) { @@ -66,7 +70,7 @@ def computeBuildToolsVersion() { return buildToolsVersion } else { - return "22.0.1" + return "23.0.1" } } project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug" @@ -102,7 +106,7 @@ android { } sourceSets.main { - jniLibs.srcDir "libs/jni" + jniLibs.srcDir "$projectDir/libs/jni" } signingConfigs { @@ -136,7 +140,15 @@ android { def variantName = variant.name.capitalize() def compileSourcesTaskName = "compile${variantName}Sources" def compileSourcesTask = project.tasks.findByName(compileSourcesTaskName) - compileSourcesTask.finalizedBy "buildMetadata" + + def generateBuildConfigTask = variant.generateBuildConfig; + generateBuildConfigTask.finalizedBy(collectAllJars) + + if(!dontRunSbg) { + collectAllJars.finalizedBy(setProperties) + } + + compileSourcesTask.finalizedBy(buildMetadata) } } @@ -158,7 +170,7 @@ dependencies { compile "com.android.support:appcompat-v7:$suppotVer" // take all jars within the libs dir - compile fileTree(dir: "libs", include: ["**/*.jar"]) + compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"]) // take all jars within the node_modules dir compile fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.jar"], exclude: '**/.bin/**') @@ -194,9 +206,8 @@ task pluginStructureCheck { } } - def createIncludeFile (filePath, fileName, dimensionName) { - println "\t+creating include.gradle file for: " + filePath + " flavor: " + fileName + println "\t+creating include.gradle file for: " + filePath def defaultIncludeFile = new File(filePath, "include.gradle") defaultIncludeFile.write "" defaultIncludeFile << "android { \n" @@ -258,10 +269,10 @@ task createDefaultIncludeFiles { } } - pluginNames.add('"' + dimensionName + '"') + flavorNames.add('"' + dimensionName + '"') if(!foundIncludeFile) { - //createIncludeFile(fl.getAbsolutePath(), fileName, dimensionName) + //createIncludeFile(fl.getAbsolutePath() ,fileName, dimensionName) createIncludeFile(fl.getAbsolutePath() , flavor, dimensionName) } } @@ -279,7 +290,7 @@ task createPluginsConfigFile { if(createPluginConfigFile) { println "\t+creating product flavors include.gradle file in $configurationsDir folder..." - def flavors = pluginNames.join(",") + def flavors = flavorNames.join(",") flavorsFile << "android { \n" flavorsFile << "\tflavorDimensions " + flavors + "\n" @@ -291,7 +302,7 @@ task createPluginsConfigFile { task pluginExtend { description "applies additional configuration" - def pathToAppGradle = "../../app/App_Resources/Android/app.gradle" + def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle" def appGradle = file(pathToAppGradle) if(appGradle.exists()) { apply from: pathToAppGradle @@ -323,13 +334,13 @@ task pluginExtend { task copyAarDependencies (type: Copy) { println "$configStage copyAarDependencies" from fileTree(dir: nodeModulesDir, include: ["**/*.aar"], exclude: '**/.bin/**').files - into "libs/aar" + into "$projectDir/libs/aar" } task addAarDependencies << { println "$configStage addAarDependencies" // manually traverse all the locally copied AAR files and add them to the project compilation dependencies list - FileTree tree = fileTree(dir: "libs/aar", include: ["**/*.aar"]) + FileTree tree = fileTree(dir: "$projectDir/libs/aar", include: ["**/*.aar"]) tree.each { File file -> // remove the extension of the file (.aar) def length = file.name.length() - 4 @@ -345,11 +356,11 @@ task addAarDependencies << { //////////////////////////////////////////////////////////////////////////////////// task cleanLocalAarFiles(type: Delete) { - delete fileTree(dir: "libs/aar", include: ["*.aar"]) + delete fileTree(dir: "$projectDir/libs/aar", include: ["*.aar"]) } task ensureMetadataOutDir { - def outputDir = file("$rootDir/metadata/output/assets/metadata") + def outputDir = file("$projectDir/metadata/output/assets/metadata") outputDir.mkdirs() } @@ -374,12 +385,35 @@ task collectAllJars { } metadataParams.add("metadata-generator.jar") - metadataParams.add("../metadata/output/assets/metadata") + metadataParams.add("$projectDir/metadata/output/assets/metadata") + def jars = new LinkedList() for(def i = 0; i < allJarPaths.size(); i++) { metadataParams.add(allJarPaths.get(i)); + def f = new File(allJarPaths.get(i)) + if (f.getName().endsWith(".jar")) { + jars.add(f) + } } + asbgProject.ext.jarFiles = jars + } +} + +task buildMetadata (type: JavaExec) { + description "builds metadata with provided jar dependencies" + + inputs.files(allJarPaths) + inputs.dir("$buildDir/intermediates/classes") + + outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat") + + doFirst { + workingDir "build-tools" + + main "-jar" - def classesDir = "$rootDir/build/intermediates/classes" + // get compiled classes to pass to metadata generator + // these need to be called after the classes have compiled + def classesDir = "$buildDir/intermediates/classes" def classesSubDirs = new File(classesDir).listFiles() @@ -398,30 +432,14 @@ task collectAllJars { if (classesDirBuildType.exists()) { metadataParams.add(classesDirBuildType.getAbsolutePath()) } - } -} - - -task buildMetadata (type: JavaExec) { - description "builds metadata with provided jar dependencies" - - inputs.files(allJarPaths) - inputs.dir("build/intermediates/classes") - - outputs.files("metadata/output/assets/metadata/treeNodeStream.dat", "metadata/output/assets/metadata/treeStringsStream.dat", "metadata/output/assets/metadata/treeValueStream.dat") - - doFirst { - workingDir "build-tools" - - main "-jar" args metadataParams.toArray() } doLast { copy { - from "metadata/output/assets/metadata" - into "src/main/assets/metadata" + from "$projectDir/metadata/output/assets/metadata" + into "$projectDir/src/main/assets/metadata" } def files = new File("${buildDir}/intermediates/res").listFiles() @@ -445,14 +463,14 @@ task buildMetadata (type: JavaExec) { exec { ignoreExitValue true - workingDir "metadata/output" + workingDir "$projectDir/metadata/output" commandLine removeCmdParams.toArray() } def addCmdParams = new ArrayList([aaptCommand, "add", tmpAPKPath, "assets/metadata/treeNodeStream.dat", "assets/metadata/treeStringsStream.dat", "assets/metadata/treeValueStream.dat"]) exec { - workingDir "metadata/output" + workingDir "$projectDir/metadata/output" commandLine addCmdParams.toArray() } } @@ -474,14 +492,20 @@ task deleteExplodedAarFolder (type: Delete) { //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// OPTIONAL TASKS ////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// -task runBindingGenerator(dependsOn: "ing:jar") { - rootProject.jarsDir = allJarPaths -} -runBindingGenerator.dependsOn("bg:jar") - -task rbg (dependsOn: "asbg:generatebindings") - +task setProperties { + project.ext.jarFiles = [] + doLast { + def list = []; + allJarPaths.each({f -> + if(f.endsWith(".jar")) { + list.add(f); + } + }) + project.jarFiles = list; + } +} +setProperties.finalizedBy("asbg:generateBindings") //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// EXECUTION ORDER ///////////////////////////////////// @@ -518,4 +542,3 @@ task buildapk { dependsOn deleteExplodedAarFolder } - From 96ea1d5ddc82429841e2b16072a85e0c6698afba Mon Sep 17 00:00:00 2001 From: blagoev Date: Wed, 13 Apr 2016 12:54:44 +0300 Subject: [PATCH 3/7] use better replacement algorithm for productFlavors in plugin supplied include.gradle files --- build/project-template-gradle/build.gradle | 75 ++++++++++++++++------ 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index ac8ca5f64..6318003f4 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -223,24 +223,63 @@ def sanatizeDimensionName(str) { return str.replaceAll(/\W/, "") } +def replaceProductFlavorInContent(content, dimension, flavor) +{ + def indexStart = content.indexOf("productFlavors"); + def index = indexStart + "productFlavors".length(); + def indexEnd = -1; + def nestedOpenBraketsCount = 0; + + while (index < content.length()) + { + print content[index] + if (content[index] == "}") + { + if (nestedOpenBraketsCount == 0) + { + indexEnd = index; + break; + } + else + { + nestedOpenBraketsCount--; + } + } + else if (content[index] == "{") + { + nestedOpenBraketsCount++; + } + + index++; + } + + if (indexEnd != -1) + { + def oldProductFlavorsText = content.substring(indexStart, indexEnd - 1); + + def newProductFlavorsText = """ + productFlavors { + "${flavor}" { + dimension "${dimension}" + } + } + """; + + return content.replace(oldProductFlavorsText, newProductFlavorsText); + } + else + { + return '' + } +} + //make sure the include.gradle file, produced by the user, has only allowed characters in dimension attribute and remove any invalid characters if necessary -def updateIncludeGradleFile(subFile, dimensionName, flavor) { - def igFile = new File(subFile.getAbsolutePath()) - def newContent = igFile.text.replaceAll(/dimension\s+["'](.+?)["']/) { fullMatch, fDimension -> - def newFg = sanatizeDimensionName(fDimension) - dimensionName = newFg - return "dimension \"$newFg\"" - } - - //println "Before patch: " + newContent - - def finalContent = newContent.replace(dimensionName + "\" {", flavor + "\" {") - - //println "Dimension: " + dimensionName + " final content: " + finalContent - - igFile.text = finalContent - - return dimensionName +def updateIncludeGradleFile(targetFile, dimensionName, flavor) +{ + def fileEntry = new File(targetFile.getAbsolutePath()); + def content = fileEntry.text; + def replacedContent = replaceProductFlavorInContent(content, dimensionName, flavor); + fileEntry.text = replacedContent; } def flavorNumber = 0 @@ -265,7 +304,7 @@ task createDefaultIncludeFiles { if(subFile.name == "include.gradle") { foundIncludeFile = true - dimensionName = updateIncludeGradleFile(subFile, dimensionName, flavor) + updateIncludeGradleFile(subFile, dimensionName, flavor) } } From c50f9e140893600f05f4e812bf092abd89023ebd Mon Sep 17 00:00:00 2001 From: blagoev Date: Wed, 13 Apr 2016 13:01:05 +0300 Subject: [PATCH 4/7] use triple double quoted strings for templates --- build/project-template-gradle/build.gradle | 29 +++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index 6318003f4..a8777b592 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -210,13 +210,17 @@ def createIncludeFile (filePath, fileName, dimensionName) { println "\t+creating include.gradle file for: " + filePath def defaultIncludeFile = new File(filePath, "include.gradle") defaultIncludeFile.write "" - defaultIncludeFile << "android { \n" - defaultIncludeFile << "\tproductFlavors {\n" - defaultIncludeFile << '\t\t"' + fileName + '" {\n' - defaultIncludeFile << '\t\t\tdimension "' + dimensionName + '"\n' - defaultIncludeFile << "\t\t}\n" - defaultIncludeFile << "\t}\n" - defaultIncludeFile << "}" + + def content = """android { + productFlavors { + ${fileName} { + dimension ${dimensionName} + } + } + }""" + + + defaultIncludeFile << content } def sanatizeDimensionName(str) { @@ -311,7 +315,6 @@ task createDefaultIncludeFiles { flavorNames.add('"' + dimensionName + '"') if(!foundIncludeFile) { - //createIncludeFile(fl.getAbsolutePath() ,fileName, dimensionName) createIncludeFile(fl.getAbsolutePath() , flavor, dimensionName) } } @@ -329,11 +332,13 @@ task createPluginsConfigFile { if(createPluginConfigFile) { println "\t+creating product flavors include.gradle file in $configurationsDir folder..." - def flavors = flavorNames.join(",") + def flavors = flavorNames.join(", ") + + def content = """android { + flavorDimensions ${flavors} + }""" - flavorsFile << "android { \n" - flavorsFile << "\tflavorDimensions " + flavors + "\n" - flavorsFile << "}\n" + flavorsFile << content } } } From 4f066c1adee017d00fe3e9964fd3d7d1f2c612f2 Mon Sep 17 00:00:00 2001 From: blagoev Date: Wed, 13 Apr 2016 13:11:13 +0300 Subject: [PATCH 5/7] create product flavor in plugin supplied include.gradle if none is present --- build/project-template-gradle/build.gradle | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index a8777b592..d527f0c00 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -206,21 +206,25 @@ task pluginStructureCheck { } } -def createIncludeFile (filePath, fileName, dimensionName) { - println "\t+creating include.gradle file for: " + filePath - def defaultIncludeFile = new File(filePath, "include.gradle") - defaultIncludeFile.write "" - +def createProductFlavorsContent(flavor, dimensionName) +{ def content = """android { productFlavors { - ${fileName} { + ${flavor} { dimension ${dimensionName} } } }""" + return content; +} + + +def createIncludeFile (filePath, flavor, dimensionName) { + println "\t + creating include.gradle file for ${filePath}" - - defaultIncludeFile << content + def defaultIncludeFile = new File(filePath, "include.gradle") + + defaultIncludeFiletext.text = createProductFlavorsContent(flavor, dimensionName); } def sanatizeDimensionName(str) { @@ -273,7 +277,8 @@ def replaceProductFlavorInContent(content, dimension, flavor) } else { - return '' + def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension); + return content.replace("android {", "android {\t ${newProductFlavorsContent}"); } } From e9fa435645499b24b4a0fa49e629341a719bdbaf Mon Sep 17 00:00:00 2001 From: blagoev Date: Wed, 13 Apr 2016 14:04:21 +0300 Subject: [PATCH 6/7] fix productflavor patching when no android content is present in plugin supplied include.gradle files. --- build/project-template-gradle/build.gradle | 61 +++++++++++++--------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index d527f0c00..a13e76cb0 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -206,16 +206,28 @@ task pluginStructureCheck { } } -def createProductFlavorsContent(flavor, dimensionName) +def createProductFlavorsContent(flavor, dimensionName, includeAndroidContent = true) { - def content = """android { - productFlavors { - ${flavor} { - dimension ${dimensionName} - } - } - }""" - return content; + if (includeAndroidContent) + { + def content = """android { + productFlavors { + "${flavor}" { + dimension "${dimensionName}" + } + } + }""" + return content; + } + else + { + def content = """productFlavors { + "${flavor}" { + dimension "${dimensionName}" + } + }""" + return content; + } } @@ -223,7 +235,6 @@ def createIncludeFile (filePath, flavor, dimensionName) { println "\t + creating include.gradle file for ${filePath}" def defaultIncludeFile = new File(filePath, "include.gradle") - defaultIncludeFiletext.text = createProductFlavorsContent(flavor, dimensionName); } @@ -265,20 +276,23 @@ def replaceProductFlavorInContent(content, dimension, flavor) { def oldProductFlavorsText = content.substring(indexStart, indexEnd - 1); - def newProductFlavorsText = """ - productFlavors { - "${flavor}" { - dimension "${dimension}" - } - } - """; + def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension, false); - return content.replace(oldProductFlavorsText, newProductFlavorsText); + return content.replace(oldProductFlavorsText, newProductFlavorsContent); } else { - def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension); - return content.replace("android {", "android {\t ${newProductFlavorsContent}"); + def androidContentExists = content.indexOf("android {") != -1; + def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension, !androidContentExists); + + if (androidContentExists) + { + return content.replace("android {", "android { ${newProductFlavorsContent}"); + } + else + { + return "${newProductFlavorsContent} \t ${content}" + } } } @@ -333,17 +347,16 @@ task createPluginsConfigFile { println "$configStage createPluginsConfigFile" def flavorsFile = new File("$configurationsDir/include.gradle") - flavorsFile.write "" //clear config file - + if(createPluginConfigFile) { - println "\t+creating product flavors include.gradle file in $configurationsDir folder..." + println "\t Creating product flavors include.gradle file in $configurationsDir folder..." def flavors = flavorNames.join(", ") def content = """android { flavorDimensions ${flavors} }""" - flavorsFile << content + flavorsFile.text = content } } } From d6ce3e75d531124772b5af092bcf48b45134e424 Mon Sep 17 00:00:00 2001 From: blagoev Date: Wed, 13 Apr 2016 23:31:06 +0300 Subject: [PATCH 7/7] rename plugin name directory to the flavor name fixes merging of flavor provided AndroidManifest and resources --- build/project-template-gradle/build.gradle | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/build/project-template-gradle/build.gradle b/build/project-template-gradle/build.gradle index a13e76cb0..f926258e8 100644 --- a/build/project-template-gradle/build.gradle +++ b/build/project-template-gradle/build.gradle @@ -305,6 +305,18 @@ def updateIncludeGradleFile(targetFile, dimensionName, flavor) fileEntry.text = replacedContent; } +def renamePluginDirToFlavorName(directory, flavor) +{ + def parentName = directory.getName(); + def parentFile = new File("src", parentName); + if (parentFile.exists()) + { + def targetDirName = new File("src", flavor); + println "Renaming plugin directory to flavor name: ${parentFile.getAbsolutePath()} -> ${targetDirName.getAbsolutePath()}"; + parentFile.renameTo(targetDirName); + } +} + def flavorNumber = 0 task createDefaultIncludeFiles { @@ -328,6 +340,7 @@ task createDefaultIncludeFiles { if(subFile.name == "include.gradle") { foundIncludeFile = true updateIncludeGradleFile(subFile, dimensionName, flavor) + renamePluginDirToFlavorName(subFile.getParentFile(), flavor); } } @@ -335,6 +348,7 @@ task createDefaultIncludeFiles { if(!foundIncludeFile) { createIncludeFile(fl.getAbsolutePath() , flavor, dimensionName) + renamePluginDirToFlavorName(fl, flavor); } } }