diff --git a/.gitignore b/.gitignore index bf94681b7..797426ac9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,4 @@ bin/ .DS_Store .settings -build-artifacts/ \ No newline at end of file +*.iml diff --git a/android-static-binding-generator/project/build.gradle b/android-static-binding-generator/project/build.gradle index 80578d915..63352275c 100644 --- a/android-static-binding-generator/project/build.gradle +++ b/android-static-binding-generator/project/build.gradle @@ -4,10 +4,10 @@ import groovy.json.JsonSlurper import groovy.io.FileType +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Paths -def isWinOs = System.properties['os.name'].toLowerCase().contains('windows') - -def astParserDir = "$projectDir/parser" def interfaceNamesFileP = "$projectDir/interfaces-names.txt" def bindingsFileP = "$projectDir/bindings.txt" def cachedJarsFilePath = "$projectDir/cached.txt" @@ -30,13 +30,12 @@ if (workersExcludeFile.exists()) { def absoluteOutDir; if (project.hasProperty("outDir")) { absoluteOutDir = project.outDir; - + if (!absoluteOutDir.exists()) { absoluteOutDir.mkdirs() } } - // def absoluteJsCodeDir = new File("./jsCodeDir").getAbsolutePath()//project.jsCodeDir def absoluteJsCodeDir; def jsCodeAbsolutePath; @@ -45,31 +44,30 @@ if (!project.hasProperty("test")) { jsCodeAbsolutePath = absoluteJsCodeDir.getAbsolutePath() } -def utf8 = java.nio.charset.StandardCharsets.UTF_8 -def current = "" +def utf8 = StandardCharsets.UTF_8 +def jarsList = "" def shouldRun = true def rootTraversed = false; def inputJsFiles = new LinkedList (); // depends on passed jars and generated interface-names -task generateInterfaceNamesList() { - +task generateInterfaceNamesList { doFirst { if(!project.hasProperty("test")) { - current = project.jarFiles + jarsList = project.jarFiles def cache = new File(cachedJarsFilePath) - + if (cache.exists()) { def contents = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(cachedJarsFilePath)), utf8).trim() - shouldRun = !contents.equals(current.toString()) + shouldRun = !contents.equals(jarsList.toString()) } if (shouldRun) { javaexec { main "-jar" - def jarsAsStr = current.toString(); + def jarsAsStr = jarsList.toString(); def jarsArr = jarsAsStr.replaceAll(/[\[\]]/, "").split(", ") def str = new LinkedList (); @@ -80,7 +78,7 @@ task generateInterfaceNamesList() { args str.toArray() } - java.nio.file.Files.write(java.nio.file.Paths.get(cachedJarsFilePath), [current.toString()], utf8) + Files.write(Paths.get(cachedJarsFilePath), [jarsList.toString()], utf8) } } } @@ -95,9 +93,7 @@ def isWorkerScript = { fileName -> } def traverseDirectory - traverseDirectory = { dir, traverseExplicitly -> - def currentDir = new File(dir) def pJsonFile = false; @@ -141,32 +137,34 @@ traverseDirectory = { dir, traverseExplicitly -> } } -task traverseJsFilesArgs << { //(jsCodeDir, bindingsFilePath, interfaceNamesFilePath, jsParserPath, jsFilesParameter) { - jsCodeAbsolutePath = jsCodeDir; - inputJsFiles = new LinkedList(); - traverseDirectory(jsCodeDir, false); +task traverseJsFilesArgs { //(jsCodeDir, bindingsFilePath, interfaceNamesFilePath, jsParserPath, jsFilesParameter) { + doLast { + jsCodeAbsolutePath = jsCodeDir; + inputJsFiles = new LinkedList(); + traverseDirectory(jsCodeDir, false); - new File(jsFilesParameter).withWriter { out -> - inputJsFiles.each {out.println it} - } + new File(jsFilesParameter).withWriter { out -> + inputJsFiles.each {out.println it} + } - def list = new ArrayList(); - list.add("node") - list.add(jsParserPath) - list.add(jsCodeDir) - list.add(bindingsFilePath) - list.add(interfaceNamesFilePath) - list.add(jsFilesParameter) - - logger.info("Task: traverseJsFilesArgs: executed with arguments: " + list.toString().replaceAll(',', '')) - def proc = list.execute() - proc.in.eachLine { line -> println line } - proc.out.close() - proc.waitFor() - - if (proc.exitValue()) { - println "gave the following error: " - println "[ERROR] ${proc.getErrorStream()}" + def list = new ArrayList(); + list.add("node") + list.add(jsParserPath) + list.add(jsCodeDir) + list.add(bindingsFilePath) + list.add(interfaceNamesFilePath) + list.add(jsFilesParameter) + + logger.info("Task: traverseJsFilesArgs: executed with arguments: " + list.toString().replaceAll(',', '')) + def proc = list.execute() + proc.in.eachLine { line -> println line } + proc.out.close() + proc.waitFor() + + if (proc.exitValue()) { + println "gave the following error: " + println "[ERROR] ${proc.getErrorStream()}" + } } } @@ -187,7 +185,7 @@ task runAstParser(type: RunAstParserTask) { // traverses the javascript code input directory // 1. traverses all root directory files // 2. all subdirectories that do not have a package.json containing a "nativescript" key are skipped -task traverseJsFiles () { +task traverseJsFiles { doFirst { // invalidate previously generated bindings.txt file // todo: remove when removing previously generated bindings is implemented @@ -274,9 +272,10 @@ task generateBindings() { inputs.dir (bindingsFile) doFirst { - if(!file(bindingsFileP).exists()) { + if (!file(bindingsFileP).exists()) { throw new GradleException("No ${bindingsFileP} was found after runAstParser task was ran! Check to see if there are any .js files inside ${jsCodeDir}") } + javaexec { main "-jar" @@ -285,7 +284,7 @@ task generateBindings() { str.add(bindingsFileP) str.add(absoluteOutDir) - def jarsAsStr = current.toString(); + def jarsAsStr = jarsList.toString(); def jarsArr = jarsAsStr.replaceAll(/[\[\]]/, "").split(", ") str.addAll(jarsArr) diff --git a/android-static-binding-generator/project/parser/js_parser.js b/android-static-binding-generator/project/parser/js_parser.js index f5744ed18..74df5899b 100644 --- a/android-static-binding-generator/project/parser/js_parser.js +++ b/android-static-binding-generator/project/parser/js_parser.js @@ -103,8 +103,6 @@ function readLinesFromFile(filePath, outArr, resolveParameter) { return reject(err); } - console.log("finished with reading lines with js files"); - return resolve(resolveParameter) }); }); diff --git a/build-artifacts/project-template-gradle/build-tools/runtime-modules/runtime/build.gradle b/build-artifacts/project-template-gradle/build-tools/runtime-modules/runtime/build.gradle deleted file mode 100644 index 8f46fc21e..000000000 --- a/build-artifacts/project-template-gradle/build-tools/runtime-modules/runtime/build.gradle +++ /dev/null @@ -1,2 +0,0 @@ -configurations.maybeCreate("default") -artifacts.add("default", file('../../../libs/runtime-libs/nativescript.aar')) \ No newline at end of file diff --git a/build-artifacts/project-template-gradle/build.gradle b/build-artifacts/project-template-gradle/build.gradle index b4aa8d36f..cc0f394f8 100644 --- a/build-artifacts/project-template-gradle/build.gradle +++ b/build-artifacts/project-template-gradle/build.gradle @@ -1,6 +1,6 @@ /* * Script builds apk in release or debug mode -* To run: +* To run: * gradle buildapk -Prelease (release mode) * gradle buildapk (debug mode -> default) * Options: @@ -18,11 +18,10 @@ * -PdontRunSbg=[true/false] */ -import groovy.json.JsonSlurper //used to parse package.json +import groovy.json.JsonSlurper import java.nio.file.Files; import java.nio.file.Paths; -import java.util.regex.Pattern; buildscript { repositories { @@ -36,111 +35,143 @@ buildscript { 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 shouldCreatePluginConfigFile = false -def configStage = "\n:config phase: " +def configStage = "\tconfig phase: " def nodeModulesDir = "../../node_modules/" -def libDir = "$projectDir/../../lib/Android/" -def flavorNames = new ArrayList() -def configDir = file(configurationsDir) +def dependenciesJson = file("dependencies.json") + +// the build script will not work with previous versions of the CLI (3.1 or earlier) +if (!dependenciesJson.exists()) { + throw new BuildCancelledException(""" +'dependencies.json' file not found. Check whether the NativeScript CLI has prepared the project beforehand, +and that your NativeScript version is 3.3, or a more recent one. To build an android project with the current +version of the {N} CLI install a previous version of the runtime package - 'tns platform add android@3.2'. +""") +} + +def nativescriptDependencies = new JsonSlurper().parseText(dependenciesJson.text) def packageJsonContents = [:] -def excludedDevDependencies = ['**/.bin/**'] 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 computeCompileSdkVersion () { - if(project.hasProperty("compileSdk")) { - return compileSdk - } - else { - return 23 - } -} +def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 23 } +def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 23 } +def computeBuildToolsVersion = { -> project.hasProperty("buildToolsVersion") ? buildToolsVersion : "25.0.2" } -def computeTargetSdkVersion() { - if(project.hasProperty("targetSdk")) { - return targetSdk - } - else { - return 23 - } -} - -def computeBuildToolsVersion() { - if(project.hasProperty("buildToolsVersion")) { - return buildToolsVersion - } - else { - return "25.0.2" - } -} project.ext.selectedBuildType = project.hasProperty("release") ? "release" : "debug" -def renameResultApks (variant) { +def renameResultApks = { variant -> def name variant.outputs.each { output -> def apkDirectory = output.packageApplication.outputFile.parentFile def abiName = ""; - if(output.getFilter(com.android.build.OutputFile.ABI)) { + if (output.getFilter(com.android.build.OutputFile.ABI)) { abiName = "-" + output.getFilter(com.android.build.OutputFile.ABI); } def apkNamePrefix = rootProject.name + "-" + variant.buildType.name + abiName name = apkNamePrefix + ".apk" output.packageApplication.outputFile = new File(apkDirectory, name); - } -} - -// gets the devDependencies declared in the package.json and excludes them from the build -task getDevDependencies { - doLast { - println "$configStage getDevDependencies" - - String content = new File("$projectDir/../../package.json").getText("UTF-8") - def jsonSlurper = new JsonSlurper() - def packageJsonMap = jsonSlurper.parseText(content) - - packageJsonContents = packageJsonMap.devDependencies; - - packageJsonContents.each { entry -> - excludedDevDependencies.add(entry.key + '/platforms/android/**/*.jar') - } } } + //////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// CONFIGURATIONS /////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// +def applyPluginsIncludeGradleConfigurations = { -> + def taskNames = project.getGradle().startParameter.taskNames + + // don't apply plugin configurations if clean is invoked + if (taskNames && taskNames.size() > 0 && taskNames.getAt(0).equals("clean")) { + return [] + } + + def configurationsDir = new File(projectDir, "build/configurations") + configurationsDir.deleteDir() + + def dimensions = [] + def includes = new ArrayList() + def flavorNumber = 0 + + nativescriptDependencies.each { dep -> + def androidDir = file("${dep.directory}/platforms/android") + if (!androidDir.exists()) { + return + } + + def packageJsonPath = file("${dep.directory}/package.json") + def packageJson = new JsonSlurper().parseText(packageJsonPath.text) + def pluginName = packageJson.name + def dimensionName = sanitizeDimensionName(pluginName) + + dimensions.add(dimensionName) + def flavor = "F${flavorNumber++}" + + def includeGradleFile = new File(androidDir, "include.gradle") + def destinationDir = file("${configurationsDir}/${pluginName}/") + def destinationIncludeGradleFile = file("${configurationsDir}/${pluginName}/include.gradle") + + Files.createDirectories(Paths.get(destinationDir.getAbsolutePath())) + + if (includeGradleFile.exists()) { + println "\t + add include.gradle from ${includeGradleFile}" + destinationIncludeGradleFile.text = modifyProductFlavorInContent(includeGradleFile.text, dimensionName, flavor) + } else { + println "\t + creating include.gradle for plugin ${file(dep.directory)}" + destinationIncludeGradleFile.text = createProductFlavorsContent(flavor, dimensionName) + } + + includes.add(destinationIncludeGradleFile.getAbsolutePath()); + + copyAndRenamePluginDirToFlavorName(androidDir, flavor); + } + + includes.each { + println "\t + applying plugin configuration from ${it}" + apply from: it + } + + return dimensions +} + +def applyAppGradleConfiguration = { -> + def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle" + def appGradle = file(pathToAppGradle) + if (appGradle.exists()) { + println "\t + applying user-defined configuration from ${appGradle}" + apply from: pathToAppGradle + } +} + android { compileSdkVersion computeCompileSdkVersion() - buildToolsVersion computeBuildToolsVersion() - + buildToolsVersion computeBuildToolsVersion() + defaultConfig { minSdkVersion 17 targetSdkVersion computeTargetSdkVersion() ndk { - abiFilters "armeabi-v7a", "x86" + abiFilters "armeabi-v7a", "x86" } } - + sourceSets.main { jniLibs.srcDir "$projectDir/libs/jni" } - + signingConfigs { release { - if(project.hasProperty("release")) { - if(project.hasProperty("ksPath") && + if (project.hasProperty("release")) { + if (project.hasProperty("ksPath") && project.hasProperty("ksPassword") && project.hasProperty("alias") && - project.hasProperty("password")) - { + project.hasProperty("password")) { + storeFile file(ksPath) storePassword ksPassword keyAlias alias @@ -154,11 +185,11 @@ android { signingConfig signingConfigs.release } } - + applicationVariants.all { variant -> renameResultApks(variant) } - + applicationVariants.all { variant -> def variantName = variant.name.capitalize() def compileSourcesTaskName = "compile${variantName}Sources" @@ -169,7 +200,7 @@ android { if(!dontRunSbg) { collectAllJars.finalizedBy(setProperties) } - + compileSourcesTask.finalizedBy(buildMetadata) // forces packaging of resources and assets AFTER producing metadata @@ -193,6 +224,12 @@ android { compileTask.dependsOn("asbg:generateBindings") } } + + def dimensions = applyPluginsIncludeGradleConfigurations() + + flavorDimensions(*dimensions) + + applyAppGradleConfiguration() } repositories { @@ -200,58 +237,65 @@ repositories { maven { url 'https://maven.google.com' } // used for local *.AAR files + def pluginDependencies = nativescriptDependencies.collect { "${it.directory}/platforms/android" } + pluginDependencies.add("libs/runtime-libs") + flatDir { - dirs 'libs/aar' + dirs pluginDependencies } } dependencies { def supportVer = "22.2.0"; - if(project.hasProperty("supportVersion")) { + if (project.hasProperty("supportVersion")) { supportVer = supportVersion } - compile "com.android.support:support-v4:$supportVer" - compile "com.android.support:appcompat-v7:$supportVer" + compile "com.android.support:support-v4:$supportVer" + compile "com.android.support:appcompat-v7:$supportVer" debugCompile "com.android.support:design:$supportVer" // take all jars within the libs dir compile fileTree(dir: "$projectDir/libs", include: ["**/*.jar"]) +} - // take all jars within the node_modules dir - compile fileTree(dir: nodeModulesDir, include: ["**/platforms/android/**/*.jar"], exclude: excludedDevDependencies) +//////////////////////////////////////////////////////////////////////////////////// +///////////////////////////// CONFIGURATION PHASE ////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// - - //when gradle has aar support this will be preferred instead of addAarDependencies - // compile files("$rootDir/libs/aar") { - // builtBy 'copyAarDependencies' - // } - copyNativeScriptAar() +task addNativeScriptRuntimePackageDependency { + def useV8Symbols = nativescriptDependencies.any { + def packageJsonPath = file("${it.directory}/package.json"); + def packageJson = new JsonSlurper().parseText(packageJsonPath.text); + return packageJson.nativescript.useV8Symbols; + } - compile project(':runtime') + def runtime = useV8Symbols ? "nativescript-regular" : "nativescript-optimized"; + println "\t + adding nativescript runtime package dependency: $runtime" + + project.dependencies.add("compile", [name: runtime, ext: "aar"]) } +task addDependenciesFromNativeScriptPlugins { + nativescriptDependencies.each { dep -> + def aarFiles = fileTree(dir: file("${dep.directory}/platforms/android"), include: ["**/*.aar"]) + aarFiles.each { aarFile -> + def length = aarFile.name.length() - 4 + def fileName = aarFile.name[0.. + println "\t + adding jar plugin dependency: " + jarFile.getAbsolutePath() + } - copy { - from "$projectDir/libs/runtime-libs/nativescript-${runtimeAarType}.aar" - into "$projectDir/libs/runtime-libs/" - rename "nativescript-${runtimeAarType}.aar", "nativescript.aar" + project.dependencies.add("compile", jarFiles) } } -//////////////////////////////////////////////////////////////////////////////////// -///////////////////////////// CONFIGURATION PHASE ////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -def updateProductFlavorsContent(flavor, dimensionName, oldContent) { +static def updateProductFlavorsContent(flavor, dimensionName, oldContent) { def endIndex = oldContent.length() - 1; def index = 0; def newContent = ""; @@ -259,9 +303,9 @@ def updateProductFlavorsContent(flavor, dimensionName, oldContent) { def dimensionFound = false; while(index <= endIndex) { - if(level == 0 && (oldContent[index] == '"' || oldContent[index] == "'")) { + if (level == 0 && (oldContent[index] == '"' || oldContent[index] == "'")) { def closingQuotes = oldContent.indexOf('"', index + 1); - if(closingQuotes == -1) { + if (closingQuotes == -1) { closingQuotes = oldContent.indexOf("'", index + 1); } @@ -270,26 +314,26 @@ def updateProductFlavorsContent(flavor, dimensionName, oldContent) { continue; } - if(oldContent[index] == "{") { - level++; + if (oldContent[index] == "{") { + level++; } - if(oldContent[index] == "}") { + if (oldContent[index] == "}") { level--; } - if(level > 0) { - if(!dimensionFound && oldContent.indexOf("dimension", index) == index) { + if (level > 0) { + if (!dimensionFound && oldContent.indexOf("dimension", index) == index) { newContent += "dimension \"${dimensionName}\""; dimensionFound = true; index += "dimension ".length(); def openingQuoutes = oldContent.indexOf('"', index); - if(openingQuoutes == -1) { + if (openingQuoutes == -1) { openingQuoutes = oldContent.indexOf("'", index); } def closingQuotes = oldContent.indexOf('"', openingQuoutes + 1); - if(closingQuotes == -1) { + if (closingQuotes == -1) { closingQuotes = oldContent.indexOf("'", openingQuoutes + 1); } @@ -305,7 +349,7 @@ def updateProductFlavorsContent(flavor, dimensionName, oldContent) { return newContent; } -def createProductFlavorsContent(flavor, dimensionName, includeAndroidContent = true) { +static def createProductFlavorsContent(flavor, dimensionName, includeAndroidContent = true) { if (includeAndroidContent) { def content = """ @@ -332,31 +376,24 @@ android { } } -def createIncludeFile (filePath, flavor, dimensionName) { - println "\t + creating include.gradle file for ${filePath}" - - def defaultIncludeFile = new File(filePath, "include.gradle") - defaultIncludeFile.text = createProductFlavorsContent(flavor, dimensionName); -} - -def sanitizeDimensionName(str) { +static def sanitizeDimensionName(str) { return str.replaceAll(/\W/, "") } -def replaceProductFlavorInContent(content, dimension, flavor) { +static def modifyProductFlavorInContent(content, dimension, flavor) { def indexStart = content.indexOf("productFlavors"); def index = indexStart + "productFlavors".length(); def indexEnd = -1; - def nestedOpenBraketsCount = 0; + def nestedOpenBracketsCount = 0; while (index < content.length()) { // print content[index]; if (content[index] == "}") { - nestedOpenBraketsCount--; + nestedOpenBracketsCount--; - if (nestedOpenBraketsCount == 0) + if (nestedOpenBracketsCount == 0) { indexEnd = index; break; @@ -364,7 +401,7 @@ def replaceProductFlavorInContent(content, dimension, flavor) { } else if (content[index] == "{") { - nestedOpenBraketsCount++; + nestedOpenBracketsCount++; } index++; @@ -376,14 +413,14 @@ def replaceProductFlavorInContent(content, dimension, flavor) { def oldProductFlavorsText = content.substring(indexStart, indexEnd + 1); def newProductFlavorsContent = updateProductFlavorsContent(flavor, dimension, oldProductFlavorsText); - + return content.replace(oldProductFlavorsText, newProductFlavorsContent); } else { def androidContentExists = content.indexOf("android {") != -1; def newProductFlavorsContent = createProductFlavorsContent(flavor, dimension, !androidContentExists); - + if (androidContentExists) { return content.replace("android {", "android { ${newProductFlavorsContent}"); @@ -395,212 +432,63 @@ def replaceProductFlavorInContent(content, dimension, flavor) { } } -// make sure the include.gradle file provided by the user has only allowed characters in dimension attribute and remove any invalid characters if necessary -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 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 { - description "creates default include.gradle files for added plugins IF NECESSARY" - println "$configStage createDefaultIncludeFiles" - def ft = file(configurationsDir) - - ft.listFiles().each { file -> - if (file.isDirectory()) { - shouldCreatePluginConfigFile = true - def hasChildrenDirs = false - file.listFiles().each { subFile -> - if (subFile.isDirectory()) { - hasChildrenDirs = true - } - } - - // if plugin is scoped - traverse its children directories - // e.g. @scope/plugin-with-android-aars - if (hasChildrenDirs) { - file.listFiles().each { subFile -> - if (subFile.isDirectory()) { - createIncludeGradleForPlugin(subFile, flavorNumber++, flavorNames) - } - } - } else { - createIncludeGradleForPlugin(file, flavorNumber++, flavorNames) - } - } - } -} +def copyFolder(source, destination) { + if (source.isDirectory()) { + Files.createDirectories(destination.toPath()); -def createIncludeGradleForPlugin(file, flavorNumber, flavorNames) { - def parentDir = new File(file.getParent()) - def parentName = parentDir.name - def dirToRename = file + def sourceFiles = source.list(); - if (parentName.indexOf("@") == 0) { - dirToRename = new File(parentName + "_" + file.name) - } + sourceFiles.each { file -> + def srcFile = new File(source, file); + def destFile = new File(destination, file); - def foundIncludeFile = false - def fileName = file.name - def dimensionName = sanitizeDimensionName(fileName) - - def flavor = "F" + flavorNumber - println "\t+found plugins: " + fileName - file.listFiles().each { subFile -> - if (subFile.name == "include.gradle") { - foundIncludeFile = true - updateIncludeGradleFile(subFile, dimensionName, flavor) - renamePluginDirToFlavorName(dirToRename, flavor); + //Recursive function call + copyFolder(srcFile, destFile); } } - - flavorNames.add('"' + dimensionName + '"') - - if (!foundIncludeFile) { - createIncludeFile(file.getAbsolutePath() , flavor, dimensionName) - renamePluginDirToFlavorName(dirToRename, flavor); - } -} - -task createPluginsConfigFile { - description "creates product flavor config file based on what plugins are added" - - if (configDir.exists()) { - println "$configStage createPluginsConfigFile" - - def flavorsFile = new File("$configurationsDir/include.gradle") - - if(shouldCreatePluginConfigFile) { - println "\t Creating product flavors include.gradle file in $configurationsDir folder..." - def flavors = flavorNames.join(", ") - - def content = """ -android { - flavorDimensions ${flavors} -} -""" - - flavorsFile.text = content + else { + // Copy the file content from one place to another + def fileName = source.getName() + def extension = fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0 ? fileName.substring(fileName.lastIndexOf(".") + 1) : ""; + // exclude aars from package, as we've already included it in the compile dependencies, and don't want it taking up space + if (extension == "aar") { + return } - } -} - -task pluginExtend { - description "applies additional configuration" - - def pathToAppGradle = "$projectDir/../../app/App_Resources/Android/app.gradle" - def appGradle = file(pathToAppGradle) - if(appGradle.exists()) { - apply from: pathToAppGradle - } - if(configDir.exists()) { - println "$configStage pluginExtend" - configDir.eachFileRecurse(groovy.io.FileType.FILES) { - if(it.name.equals('include.gradle')) { - println "\t+applying configuration from: " + it - apply from: it - } - } + Files.copy(source.toPath(), destination.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING); } } -//// doesn't work unless task is explicitly called (TODO: research configurations hook) -// addAarDependencies.dependsOn(copyAarDependencies) -// createDefaultIncludeFiles.dependsOn(addAarDependencies) -// createPluginsConfigFile.dependsOn(createDefaultIncludeFiles) -// pluginExtend.dependsOn(createPluginsConfigFile) - - -//////////////////////////////////////////////////////////////////////////////////// -///////////////////////////// BEFORE EXECUTION ///////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -// we need to copy all dependencies into a flat dir, as pointed by the repositories configurations at the top -task copyAarDependencies (type: Copy) { - def filterAarFilesFn = { path, attrs -> - String pathString = path.toString(); - def isBin = Pattern.matches(".*/\\.bin/.*", pathString); - def isAar = Pattern.matches(".*\\.aar\$", pathString); - return !isBin && isAar; - } - - def mapToStringFn = { path -> - return path.toString(); - } +def copyAndRenamePluginDirToFlavorName(directory, flavor) { + def targetDir = file("src/${flavor}") - Object[] files = Files.find( - Paths.get("$projectDir", "$nodeModulesDir"), - Integer.MAX_VALUE, - filterAarFilesFn, - java.nio.file.FileVisitOption.FOLLOW_LINKS - ) - .map(mapToStringFn) - .toArray(); - - into "$projectDir/libs/aar" - from files + copyFolder(directory, targetDir) } -task addAarDependencies { - doLast { - 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"]) - tree.each { File file -> - // remove the extension of the file (.aar) - def length = file.name.length() - 4 - def fileName = file.name[0.. logger.info("Task: collectAllJars: dependency file: " + dependencyFile.getAbsolutePath()) allJarPaths.add(dependencyFile.getAbsolutePath()) } - + allJarPaths.add(androidJar); - + def ft = fileTree(dir: explodedAarDir, include: "**/*.jar") ft.each { currentJarFile -> allJarPaths.add(currentJarFile.getAbsolutePath()) @@ -609,30 +497,30 @@ task collectAllJars { metadataParams.add("metadata-generator.jar"); metadataParams.add("$projectDir/metadata/output/assets/metadata"); def jars = new LinkedList() - for(def i = 0; i < allJarPaths.size(); i++) { + 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 { - // get compiled classes to pass to metadata generator - // these need to be called after the classes have compiled - def classesDir = "$buildDir/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() def selectedBuildType = project.ext.selectedBuildType @@ -657,7 +545,7 @@ task buildMetadata (type: JavaExec) { logger.info("Task buildMetadata: Call metadata-generator.jar with arguments: " + metadataParams.toString().replaceAll(',', '')) args metadataParams.toArray() } - + doLast { copy { from "$projectDir/metadata/output/assets/metadata" @@ -699,7 +587,7 @@ generateTypescriptDefinitions.onlyIf { project.hasProperty("generateTypings") && Boolean.parseBoolean(project.generateTypings) } -def shouldIncludeDirForTypings(path, includeDirs) { +static def shouldIncludeDirForTypings(path, includeDirs) { for (String p: includeDirs) { if (path.indexOf(p) > -1) { return true; @@ -720,9 +608,7 @@ task copyTypings { } } -copyTypings.onlyIf({ - generateTypescriptDefinitions.didWork; -}) +copyTypings.onlyIf { generateTypescriptDefinitions.didWork } task validateAppIdMatch { doLast { @@ -747,18 +633,19 @@ task validateAppIdMatch { //////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// OPTIONAL TASKS ////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// + task setProperties { project.ext.jarFiles = [] doLast { def list = []; - allJarPaths.each({f -> + allJarPaths.each({f -> if(f.endsWith(".jar")) { list.add(f); } }) project.jarFiles = list; } -} +} setProperties.finalizedBy("asbg:generateBindings", generateTypescriptDefinitions) @@ -766,31 +653,13 @@ setProperties.finalizedBy("asbg:generateBindings", generateTypescriptDefinitions ////////////////////////////// EXECUTION ORDER ///////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// -// -- configuration phase -// 1. Copy *.aar dependencies -// 2. Add *.aar dependencies -// 3. create default include files -// 4. create plugins config file -// 5. plugin extend (apply from include files) - -// --execution phase - -ensureMetadataOutDir.dependsOn(cleanLocalAarFiles) collectAllJars.dependsOn(ensureMetadataOutDir) buildMetadata.dependsOn(collectAllJars) generateTypescriptDefinitions.finalizedBy(copyTypings) -//DO NOT UNCOMMENT -// mergeAssets.dependsOn(copyMetadata) -> look in CONFIGURATIONS(top) in android.applicationVariants to see how it's done - task buildapk { - // problem is compile dependencies need to be changed before configuration stage - // and this is the only way so far - tasks.copyAarDependencies.execute() - tasks.addAarDependencies.execute() - //done to build only necessary apk - if(project.hasProperty("release")) { + if (project.hasProperty("release")) { dependsOn "assembleRelease" } else { @@ -800,26 +669,23 @@ task buildapk { //////// custom clean /////////// task deleteMetadata (type: Delete){ - delete "$projectDir/metadata/output" + delete "$projectDir/metadata/output", "$projectDir/src/main/assets/metadata" } task deleteFlavors (type: Delete){ doLast { def srcDir = new File("$projectDir/src") srcDir.listFiles().each({ f -> - if(!f.getName().equals("main") && - !f.getName().equals("debug") && - !f.getName().equals("release")) { + def dirName = f.getName() + if (dirName != "main" && + dirName != "debug" && + dirName != "release") { delete f } }) } } -task deleteConfigurations (type: Delete) { - delete "$projectDir/configurations" -} - task deleteGeneratedBindings(type: Delete) { delete "$projectDir/src/main/java/com/tns/gen" } @@ -827,6 +693,5 @@ task deleteGeneratedBindings(type: Delete) { buildapk.finalizedBy("validateAppIdMatch"); deleteMetadata.dependsOn(":asbg:clean") deleteFlavors.dependsOn(deleteMetadata) -deleteConfigurations.dependsOn(deleteFlavors) -deleteGeneratedBindings.dependsOn(deleteConfigurations) +deleteGeneratedBindings.dependsOn(deleteFlavors) clean.dependsOn(deleteGeneratedBindings)