diff --git a/.travis.yml b/.travis.yml index 3aa1b1c..85d5f78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,5 +42,5 @@ matrix: KBUILD=android JAVA_OPTS=-Xmx2g script: - - ./gradlew -s -i check build + - ./gradlew -s -i lint testDebugUnitTest diff --git a/build.gradle b/build.gradle deleted file mode 100644 index f9d5c12..0000000 --- a/build.gradle +++ /dev/null @@ -1,335 +0,0 @@ -buildscript { - ext.hasAndroid = (System.getProperty("sdk.dir") != null) || (System.getenv("ANDROID_HOME") != null) - - if (!ext.hasAndroid) { - def trySdkDir = new File(System.getProperty("user.home") + "/Library/Android/sdk") - if (trySdkDir.exists()) { - new File(rootDir, "local.properties").write("sdk.dir=${trySdkDir.absolutePath}") - ext.hasAndroid = true - } - } - - if (ext.hasAndroid) { - repositories { - mavenLocal() - mavenCentral() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' - } - } -} - -plugins { - id 'kotlin-multiplatform' version '1.3.20' - id 'com.moowork.node' version '1.2.0' -} - -allprojects { - repositories { - mavenLocal() - maven { url "https://dl.bintray.com/soywiz/soywiz" } - jcenter() - google() - } - - if (project.file('build.project.gradle').exists()) { - apply from: project.file('build.project.gradle') - } -} - -def hasAndroid = ext.hasAndroid - -subprojects { - if (project.name == "template") return - - apply plugin: 'kotlin-multiplatform' - apply plugin: 'com.moowork.node' - - if (hasAndroid) { - apply plugin: 'com.android.library' - - android { - compileSdkVersion 28 - defaultConfig { - minSdkVersion 18 - targetSdkVersion 28 - } - } - } - - kotlin { - targets { - if (hasAndroid) { - fromPreset(presets.android, 'android') { - publishLibraryVariants("release", "debug") - } - } - fromPreset(presets.iosX64, 'iosX64') - fromPreset(presets.iosArm32, 'iosArm32') - fromPreset(presets.iosArm64, 'iosArm64') - fromPreset(presets.macosX64, 'macosX64') - fromPreset(presets.linuxX64, 'linuxX64') - fromPreset(presets.mingwX64, 'mingwX64') - fromPreset(presets.jvm, 'jvm') - fromPreset(presets.js, 'js') { - compilations.main { - compileKotlinJs.kotlinOptions { - languageVersion = "1.3" - sourceMap = true - metaInfo = true - moduleKind = "umd" - } - compileTestKotlinJs.kotlinOptions { - languageVersion = "1.3" - moduleKind = "umd" - } - } - } - - // Only enable when loaded in IDEA (we use a property for detection). In CLI that would produce an "expect" error. - - if (System.getProperty("idea.version") != null) { - if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) { - kotlin.targets.fromPreset(kotlin.presets.mingwX64, 'nativeCommon') - kotlin.targets.fromPreset(kotlin.presets.mingwX64, 'nativePosix') - } else if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_MAC)) { - kotlin.targets.fromPreset(kotlin.presets.macosX64, 'nativeCommon') - kotlin.targets.fromPreset(kotlin.presets.macosX64, 'nativePosix') - } else { - kotlin.targets.fromPreset(kotlin.presets.linuxX64, 'nativeCommon') - kotlin.targets.fromPreset(kotlin.presets.linuxX64, 'nativePosix') - } - } - } - sourceSets { - nativeCommonMain - nativeCommonTest - nativePosixMain - if (hasAndroid) { - androidMain { - //dependsOn jvmMain - } - androidTest { - //dependsOn jvmTest - } - } - mingwX64Main { - dependsOn nativeCommonMain - } - mingwX64Test { - dependsOn nativeCommonTest - } - configure([iosX64Main, iosArm32Main, iosArm64Main, macosX64Main, linuxX64Main]) { - dependsOn nativeCommonMain - dependsOn nativePosixMain - } - configure([iosX64Test, iosArm32Test, iosArm64Test, macosX64Test, linuxX64Test]) { - dependsOn nativeCommonTest - } - } - } - - dependencies { - commonMainImplementation "org.jetbrains.kotlin:kotlin-stdlib-common" - commonTestImplementation "org.jetbrains.kotlin:kotlin-test-annotations-common" - commonTestImplementation "org.jetbrains.kotlin:kotlin-test-common" - - if (hasAndroid) { - androidMainImplementation "org.jetbrains.kotlin:kotlin-stdlib" - androidTestImplementation "org.jetbrains.kotlin:kotlin-test" - androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit" - } - - jsMainImplementation "org.jetbrains.kotlin:kotlin-stdlib-js" - jsTestImplementation "org.jetbrains.kotlin:kotlin-test-js" - - jvmMainImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - jvmTestImplementation "org.jetbrains.kotlin:kotlin-test" - jvmTestImplementation "org.jetbrains.kotlin:kotlin-test-junit" - } - -// Javascript test configuration - - def korlibsDir = new File(System.getProperty("user.home"), ".korlibs") - korlibsDir.mkdirs() - - node { - version = '8.11.4' - download = true - workDir = new File(korlibsDir, "nodejs") - npmWorkDir = new File(korlibsDir, "npm") - yarnWorkDir = new File(korlibsDir, "yarn") - nodeModulesDir = new File(korlibsDir, "node_modules") - } - - def jsCompilations = kotlin.targets.js.compilations - task installMocha(type: NpmTask) { - onlyIf { !(new File(node.nodeModulesDir, "mocha")).exists() } - args = ["install", "mocha@5.2.0"] - } - - task populateNodeModules { - doLast { - copy { - from "${node.nodeModulesDir}" - from jsCompilations.main.output.allOutputs - from jsCompilations.test.output.allOutputs - jsCompilations.test.runtimeDependencyFiles.each { - if (it.exists() && !it.isDirectory()) { - from zipTree(it.absolutePath).matching { include '*.js' } - } - } - afterEvaluate { - for (sourceSet in kotlin.sourceSets) { - from sourceSet.resources - } - } - into "$buildDir/node_modules" - } - } - } - - task runMocha(type: NodeTask, dependsOn: [jsCompilations.test.compileKotlinTaskName, installMocha, populateNodeModules]) { - script = file("$buildDir/node_modules/mocha/bin/mocha") - workingDir = file("$buildDir/node_modules") - args = ["--timeout", "15000", "${project.name}_test.js"] - } - - task jsInstallMochaHeadlessChrome(type: NpmTask) { - onlyIf { !(new File("${node.nodeModulesDir}/mocha-headless-chrome")).exists() } - args = ["install", "mocha-headless-chrome@2.0.1"] - } - - task jsTestChrome(type: NodeTask, dependsOn: [jsCompilations.test.compileKotlinTaskName, jsInstallMochaHeadlessChrome, installMocha, populateNodeModules]) { - doFirst { - new File("$buildDir/node_modules/tests.html").write(""" - - - - Mocha Tests - - - - - -
- - - - - """) - } - script = file("${node.nodeModulesDir}/mocha-headless-chrome/bin/start") - args = ['-f', "$buildDir/node_modules/tests.html", "-a", "no-sandbox", "-a", "disable-setuid-sandbox", "-a", "allow-file-access-from-files"] - } - - afterEvaluate { - //println(macosX64Test.outputDir) - //println(macosX64Test) - //println(macosX64Test.class) - - for (target in ["macosX64", "linuxX64", "mingwX64"]) { - String taskName = "copyResourcesToExecutable_${target}" - def targetTestTask = tasks.getByName("${target}Test") - tasks.create(name: taskName, type: Copy) { - for (sourceSet in kotlin.sourceSets) { - from sourceSet.resources - } - into new File(targetTestTask.inputs.properties.executable).parentFile - } - - //println() - //dump(linkTestMacosX64.outputs) - targetTestTask.dependsOn(taskName) - } - } - - [kotlin.targets.js, kotlin.targets.metadata].each { target -> - target.compilations.main.kotlinSourceSets.resources.collectMany { it.srcDirs }.each { - tasks.jsJar.from it - } - } - -// Only run JS tests if not in windows - if (!org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) { - jsTest.dependsOn runMocha - } - -// Fix for https://github.com/srs/gradle-node-plugin/issues/301 - repositories.whenObjectAdded { - if (it instanceof IvyArtifactRepository) { - metadataSources { - artifact() - } - } - } - -// Publishing - group 'com.soywiz' - version projectVersion - apply plugin: 'maven-publish' - - def pomBaseData = { - licenses { - license { - name project.property("project.license.name") - url project.property("project.license.url") - } - } - scm { - url project.property("project.scm.url") - } - } - - def generatePom = { pom -> - pom.withXml { - def root = it.asNode() - root.appendNode('name', project.name) - root.appendNode('description', project.property("project.description")) - root.appendNode('url', project.property("project.scm.url")) - root.children().last() + pomBaseData - } - } - - ext.generatePom = generatePom - - def publishUser = rootProject.findProperty('BINTRAY_USER') ?: project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER') - def publishPassword = rootProject.findProperty('BINTRAY_KEY') ?: project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY') - - if (publishUser && publishPassword) { - publishing { - repositories { - maven { - credentials { - username publishUser - password publishPassword - } - url "https://api.bintray.com/maven/soywiz/soywiz/${project.property('project.package')}/" - } - } - - afterEvaluate { - configure(publications) { - //println(pom.packaging) - generatePom(pom) - if (pom.packaging == 'aar') { - pom.withXml { - Node root = it.asNode() - NodeList scope = root.dependencies.dependency.scope - for (Node node in scope.asList()) { - node.setValue("compile") - //println(node) - } - } - } - } - } - } - } -} diff --git a/build.project.gradle b/build.project.gradle deleted file mode 100644 index 7d82dc7..0000000 --- a/build.project.gradle +++ /dev/null @@ -1,2 +0,0 @@ -dependencies { -} diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore new file mode 100644 index 0000000..12eb6a9 --- /dev/null +++ b/buildSrc/.gitignore @@ -0,0 +1,2 @@ +/.gradle +/build diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000..cf35c05 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,19 @@ +plugins { + id "org.jetbrains.kotlin.jvm" version "1.3.21" +} + + +repositories { + mavenLocal() + mavenCentral() + google() + maven { url = uri("https://plugins.gradle.org/m2/") } +} + +dependencies { + testImplementation("junit:junit:4.12") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin") + implementation("com.android.tools.build:gradle:3.3.1") + implementation("com.moowork.gradle:gradle-node-plugin:1.2.0") +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/KorlibsPlugin.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/KorlibsPlugin.kt new file mode 100644 index 0000000..3a6d744 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/KorlibsPlugin.kt @@ -0,0 +1,130 @@ +package com.soywiz.korlibs + +import com.moowork.gradle.node.NodeExtension +import com.moowork.gradle.node.npm.NpmTask +import com.soywiz.korlibs.modules.* +import com.soywiz.korlibs.targets.* +import org.gradle.api.* +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation +import java.io.* + +class KorlibsPlugin : Plugin { + override fun apply(project: Project) = project { + val korlibs = KorlibsExtension(this) + extensions.add("korlibs", korlibs) + + plugins.apply("kotlin-multiplatform") + plugins.apply("com.moowork.node") + + configureKorlibsRepos() + + // Platforms + configureTargetCommon() + configureTargetAndroid() + configureTargetNative() + configureTargetJavaScript() + configureTargetJVM() + + // Publishing + configurePublishing() + } +} + +class KorlibsExtension(val project: Project) { + var hasAndroid = (System.getProperty("sdk.dir") != null) || (System.getenv("ANDROID_HOME") != null) + + init { + if (!hasAndroid) { + val trySdkDir = File(System.getProperty("user.home") + "/Library/Android/sdk") + if (trySdkDir.exists()) { + File(project.rootDir, "local.properties").writeText("sdk.dir=${trySdkDir.absolutePath}") + hasAndroid = true + } + } + } + + fun dependencyProject(name: String) = project { + dependencies { + add("commonMainApi", project(name)) + add("commonTestImplementation", project(name)) + } + } + + val ALL_NATIVE_TARGETS = listOf("iosArm64", "iosArm32", "iosX64", "linuxX64", "macosX64", "mingwX64") + val ALL_TARGETS = listOf("android", "js", "jvm", "metadata") + ALL_NATIVE_TARGETS + + @JvmOverloads + fun dependencyMulti(group: String, name: String, version: String, targets: List = ALL_TARGETS, suffixCommonRename: Boolean = false, androidIsJvm: Boolean = false) = project { + dependencies { + for (target in targets) { + val base = when (target) { + "metadata" -> "common" + else -> target + } + val suffix = when { + target == "android" && androidIsJvm -> "-jvm" + target == "metadata" && suffixCommonRename -> "-common" + else -> "-${target.toLowerCase()}" + } + + val packed = "$group:$name$suffix:$version" + add("${base}MainApi", packed) + add("${base}TestImplementation", packed) + } + } + } + + @JvmOverloads + fun dependencyMulti(dependency: String, targets: List = ALL_TARGETS) { + val (group, name, version) = dependency.split(":", limit = 3) + return dependencyMulti(group, name, version, targets) + } + + @JvmOverloads + fun dependencyNodeModule(name: String, version: String) = project { + val node = extensions.getByType(NodeExtension::class.java) + + val installNodeModule = tasks.create("installJs${name.capitalize()}") { + onlyIf { !File(node.nodeModulesDir, name).exists() } + setArgs(arrayListOf("install", "$name@$version")) + } + + tasks.getByName("jsTestNode").dependsOn(installNodeModule) + } + + data class CInteropTargets(val name: String, val targets: List) + + val cinterops = arrayListOf() + + + @JvmOverloads + fun dependencyCInterops(name: String, targets: List) = project { + cinterops += CInteropTargets(name, targets) + for (target in targets) { + (kotlin.targets[target].compilations["main"] as KotlinNativeCompilation).apply { + cinterops.apply { + maybeCreate(name).apply { + } + } + } + } + } + + @JvmOverloads + fun dependencyCInteropsExternal(dependency: String, cinterop: String, targets: List = ALL_NATIVE_TARGETS) { + dependencyMulti("$dependency:cinterop-$cinterop@klib", targets) + } + + @JvmOverloads + fun exposeVersion(name: String = project.name) { + project.projectDir["src/commonMain/kotlin/com/soywiz/$name/internal/${name.capitalize()}Version.kt"].text = """ + package com.soywiz.$name.internal + + internal const val ${name.toUpperCase()}_VERSION = "${project.version}" + """.trimIndent() + } +} + +val Project.korlibs get() = extensions.getByType(KorlibsExtension::class.java) +fun Project.korlibs(callback: KorlibsExtension.() -> Unit) = korlibs.apply(callback) +val Project.hasAndroid get() = korlibs.hasAndroid diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Publishing.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Publishing.kt new file mode 100644 index 0000000..5beeb0a --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Publishing.kt @@ -0,0 +1,88 @@ +package com.soywiz.korlibs.modules + +import com.soywiz.korlibs.korlibs +import com.soywiz.korlibs.toXmlString +import groovy.util.* +import groovy.xml.* +import org.gradle.api.* +import org.gradle.api.publish.* +import org.gradle.api.publish.maven.* + +fun Project.configurePublishing() { + // Publishing + val publishUser = (rootProject.findProperty("BINTRAY_USER") ?: project.findProperty("bintrayUser") ?: System.getenv("BINTRAY_USER"))?.toString() + val publishPassword = (rootProject.findProperty("BINTRAY_KEY") ?: project.findProperty("bintrayApiKey") ?: System.getenv("BINTRAY_API_KEY"))?.toString() + + plugins.apply("maven-publish") + + if (publishUser != null && publishPassword != null) { + val publishing = extensions.getByType(PublishingExtension::class.java) + publishing.apply { + repositories { + it.maven { + it.credentials { + it.username = publishUser + it.setPassword(publishPassword) + } + it.url = uri("https://api.bintray.com/maven/soywiz/soywiz/${project.property("project.package")}/") + } + } + afterEvaluate { + configure(publications) { + val publication = it as MavenPublication + publication.pom.withXml { + it.asNode().apply { + appendNode("name", project.name) + appendNode("description", project.property("project.description")) + appendNode("url", project.property("project.scm.url")) + appendNode("licenses").apply { + appendNode("license").apply { + appendNode("name").setValue(project.property("project.license.name")) + appendNode("url").setValue(project.property("project.license.url")) + } + } + appendNode("scm").apply { + appendNode("url").setValue(project.property("project.scm.url")) + } + + // Workaround for kotlin-native cinterops without gradle metadata + if (korlibs.cinterops.isNotEmpty()) { + val dependenciesList = (this.get("dependencies") as NodeList) + if (dependenciesList.isNotEmpty()) { + (dependenciesList.first() as Node).apply { + for (cinterop in korlibs.cinterops.filter { it.targets.contains(publication.name) }) { + appendNode("dependency").apply { + appendNode("groupId").setValue("${project.group}") + appendNode("artifactId").setValue("${project.name}-${publication.name.toLowerCase()}") + appendNode("version").setValue("${project.version}") + appendNode("type").setValue("klib") + appendNode("classifier").setValue("cinterop-${cinterop.name}") + appendNode("scope").setValue("compile") + appendNode("exclusions").apply { + appendNode("exclusion").apply { + appendNode("artifactId").setValue("*") + appendNode("groupId").setValue("*") + } + } + } + } + } + } + } + + // Changes runtime -> compile in Android's AAR publications + if (publication.pom.packaging == "aar") { + val nodes = this.getAt(QName("dependencies")).getAt("dependency").getAt("scope") + for (node in nodes) { + (node as Node).setValue("compile") + } + } + } + } + } + } + } + } else { + println("Publishing is not enabled. Was not able to determine either `publishUser` or `publishPassword`") + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Repositories.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Repositories.kt new file mode 100644 index 0000000..a1a3c34 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Repositories.kt @@ -0,0 +1,32 @@ +package com.soywiz.korlibs.modules + +import org.gradle.api.* + +fun Project.configureKorlibsRepos() { + allprojects { + repositories.apply { + mavenLocal().apply { + content { + it.excludeGroup("Kotlin/Native") + } + } + maven { + it.url = uri("https://dl.bintray.com/soywiz/soywiz") + it.content { + it.includeGroup("com.soywiz") + it.excludeGroup("Kotlin/Native") + } + } + jcenter() { + it.content { + it.excludeGroup("Kotlin/Native") + } + } + google().apply { + content { + it.excludeGroup("Kotlin/Native") + } + } + } + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Android.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Android.kt new file mode 100644 index 0000000..3eaa43b --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Android.kt @@ -0,0 +1,29 @@ +package com.soywiz.korlibs.targets + +import com.soywiz.korlibs.* +import org.gradle.api.* + +fun Project.configureTargetAndroid() { + if (korlibs.hasAndroid) { + plugins.apply("com.android.library") + extensions.getByType(com.android.build.gradle.LibraryExtension::class.java).apply { + compileSdkVersion(28) + defaultConfig { + it.minSdkVersion(18) + it.targetSdkVersion(28) + } + } + + gkotlin.apply { + android { + publishLibraryVariants("release", "debug") + } + } + + dependencies { + add("androidMainImplementation", "org.jetbrains.kotlin:kotlin-stdlib") + add("androidTestImplementation", "org.jetbrains.kotlin:kotlin-test") + add("androidTestImplementation", "org.jetbrains.kotlin:kotlin-test-junit") + } + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Common.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Common.kt new file mode 100644 index 0000000..a0384bd --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Common.kt @@ -0,0 +1,11 @@ +package com.soywiz.korlibs.targets + +import org.gradle.api.* + +fun Project.configureTargetCommon() { + dependencies.apply { + add("commonMainImplementation", "org.jetbrains.kotlin:kotlin-stdlib-common") + add("commonTestImplementation", "org.jetbrains.kotlin:kotlin-test-annotations-common") + add("commonTestImplementation", "org.jetbrains.kotlin:kotlin-test-common") + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JVM.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JVM.kt new file mode 100644 index 0000000..bd836e0 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JVM.kt @@ -0,0 +1,24 @@ +package com.soywiz.korlibs.targets + +import com.soywiz.korlibs.* +import org.gradle.api.* +import org.gradle.api.tasks.testing.* + +fun Project.configureTargetJVM() { + gkotlin.apply { + jvm() + } + + dependencies.apply { + add("jvmMainImplementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk8") + add("jvmTestImplementation", "org.jetbrains.kotlin:kotlin-test") + add("jvmTestImplementation", "org.jetbrains.kotlin:kotlin-test-junit") + } + + // Headless testing on JVM (so we can use GWT) + tasks { + (getByName("jvmTest") as Test).apply { + jvmArgs = (jvmArgs ?: arrayListOf()) + arrayListOf("-Djava.awt.headless=true") + } + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JavaScript.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JavaScript.kt new file mode 100644 index 0000000..4c65eaa --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/JavaScript.kt @@ -0,0 +1,162 @@ +package com.soywiz.korlibs.targets + +import com.soywiz.korlibs.* +import org.gradle.api.* +import org.gradle.api.artifacts.repositories.* +import java.io.* +import com.moowork.gradle.node.* +import com.moowork.gradle.node.npm.* +import com.moowork.gradle.node.task.* +import org.apache.tools.ant.taskdefs.condition.* +import org.gradle.api.tasks.* +import org.gradle.api.tasks.bundling.* +import org.gradle.api.tasks.testing.* + +fun Project.configureTargetJavaScript() { + gkotlin.apply { + js { + compilations.all { + it.kotlinOptions.apply { + languageVersion = "1.3" + sourceMap = true + metaInfo = true + moduleKind = "umd" + } + } + } + } + + dependencies.apply { + add("jsMainImplementation", "org.jetbrains.kotlin:kotlin-stdlib-js") + add("jsTestImplementation", "org.jetbrains.kotlin:kotlin-test-js") + } + + // Javascript test configuration + val korlibsDir = File(System.getProperty("user.home"), ".korlibs").apply { mkdirs() } + val node = extensions.getByType(NodeExtension::class.java) + val globalNodeModulesDir = korlibsDir["node_modules"] + val localNodeModulesDir = buildDir["node_modules"] + + run { + node.apply { + version = "8.11.4" + download = true + workDir = korlibsDir["nodejs"] + npmWorkDir = korlibsDir["npm"] + yarnWorkDir = korlibsDir["yarn"] + nodeModulesDir = globalNodeModulesDir + } + + // Fix for https://github.com/srs/gradle-node-plugin/issues/301 + repositories.whenObjectAdded { + if (this is IvyArtifactRepository) { + metadataSources { + it.artifact() + } + } + } + + // Small optimization + project.tasks.getByName("nodeSetup").onlyIf { !korlibsDir["nodejs"].exists() } + } + + val jsCompilations = gkotlin.targets.js.compilations + + val installMocha = tasks.create("installMocha") { + onlyIf { !node.nodeModulesDir["mocha"].exists() } + setArgs(listOf("install", "mocha@5.2.0")) + } + + val populateNodeModules = tasks.create("populateNodeModules") { + afterEvaluate { + from(globalNodeModulesDir) + + from(jsCompilations.main.output.allOutputs) + from(jsCompilations.test.output.allOutputs) + for (f in jsCompilations.test.runtimeDependencyFiles) { + if (f.exists() && !f.isDirectory) { + from(zipTree(f.absolutePath).matching { it.include("*.js") }) + } + } + for (sourceSet in gkotlin.sourceSets) { + from(sourceSet.resources) + } + + //println(node.nodeModulesDir) + //println("$buildDir/node_modules") + into(localNodeModulesDir) + } + } + + val jsTestNode = tasks.create("jsTestNode") { + dependsOn(jsCompilations.test.compileKotlinTask, installMocha, populateNodeModules) + + val resultsFile = buildDir["node-results/results.json"] + setScript(file("$buildDir/node_modules/mocha/bin/mocha")) + setWorkingDir(file("$buildDir/node_modules")) + setArgs(listOf("-c", "--timeout", "15000", "${project.name}_test.js", "-o", resultsFile)) + inputs.files(jsCompilations.test.compileKotlinTask.outputFile, jsCompilations.main.compileKotlinTask.outputFile) + outputs.file(resultsFile) + } + + val jsInstallMochaHeadlessChrome = tasks.create("jsInstallMochaHeadlessChrome") { + onlyIf { !node.nodeModulesDir["mocha-headless-chrome"].exists() } + setArgs(listOf("install", "mocha-headless-chrome@2.0.1")) + } + + val jsTestChrome = tasks.create("jsTestChrome") { + dependsOn(jsCompilations.test.compileKotlinTask, jsInstallMochaHeadlessChrome, installMocha, populateNodeModules) + + val resultsFile = buildDir["chrome-results/results.json"] + doFirst { + buildDir["node_modules/tests.html"].text = """ + + + + Mocha Tests + + + + + +
+ + + + + """.trimIndent() + } + setScript(node.nodeModulesDir["mocha-headless-chrome/bin/start"]) + setArgs(listOf("-f", "$buildDir/node_modules/tests.html", "-a", "no-sandbox", "-a", "disable-setuid-sandbox", "-a", "allow-file-access-from-files", "-o", resultsFile)) + inputs.files(jsCompilations.test.compileKotlinTask.outputFile, jsCompilations.main.compileKotlinTask.outputFile) + outputs.file(resultsFile) + } + + + // Include resources from JS and Metadata (common) into the JS JAR + val jsJar = tasks.getByName("jsJar") as Jar + val jsTest = tasks.getByName("jsTest") as Test + + for (target in listOf(kotlin.targets.js, kotlin.targets.metadata)) { + //for (target in listOf(kotlin.targets.js)) { + for (sourceSet in target.compilations.main.kotlinSourceSets) { + for (it in sourceSet.resources.srcDirs) { + jsJar.from(it) + } + } + } + + // Only run JS tests if not in windows + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + jsTest.dependsOn(jsTestNode) + + // Except on travis (we have a separate target for it) + if (System.getenv("TRAVIS") == null) { + jsTest.dependsOn(jsTestChrome) + } + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Native.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Native.kt new file mode 100644 index 0000000..03ad6f9 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/targets/Native.kt @@ -0,0 +1,92 @@ +package com.soywiz.korlibs.targets + +import com.soywiz.korlibs.* +import org.apache.tools.ant.taskdefs.condition.* +import org.gradle.api.* +import org.gradle.api.tasks.* +import java.io.* + +fun Project.configureTargetNative() { + gkotlin.apply { + iosX64() + iosArm32() + iosArm64() + macosX64() + linuxX64() + mingwX64() + + if (System.getProperty("idea.version") != null) { + when { + Os.isFamily(Os.FAMILY_WINDOWS) -> run { mingwX64("nativeCommon"); mingwX64("nativePosix") } + Os.isFamily(Os.FAMILY_MAC) -> run { macosX64("nativeCommon"); macosX64("nativePosix") } + else -> run { linuxX64("nativeCommon"); linuxX64("nativePosix") } + } + } + + sourceSets.apply { + fun dependants(name: String, on: Set) { + val main = maybeCreate("${name}Main") + val test = maybeCreate("${name}Test") + for (o in on) { + maybeCreate("${o}Main").dependsOn(main) + maybeCreate("${o}Test").dependsOn(test) + } + } + + val none = setOf() + val android = if (hasAndroid) setOf() else setOf("android") + val jvm = setOf("jvm") + val js = setOf("js") + val ios = setOf("iosX64", "iosArm32", "iosArm64") + val macos = setOf("macosX64") + val linux = setOf("linuxX64") + val mingw = setOf("mingwX64") + val apple = ios + macos + val allNative = apple + linux + mingw + val jvmAndroid = jvm + android + val allTargets = allNative + js + jvm + android + + dependants("iosCommon", ios) + dependants("nativeCommon", allNative) + dependants("nonNativeCommon", allTargets - allNative) + dependants("nativePosix", allNative - mingw) + dependants("nativePosixNonApple", allNative - mingw - apple) + dependants("nativePosixApple", apple) + dependants("nonJs", allTargets - js) + } + } + + afterEvaluate { + for (target in listOf("macosX64", "linuxX64", "mingwX64")) { + val taskName = "copyResourcesToExecutable_$target" + val targetTestTask = tasks.getByName("${target}Test") as Exec + val compileTestTask = tasks.getByName("compileTestKotlin${target.capitalize()}") + val compileMainask = tasks.getByName("compileKotlin${target.capitalize()}") + + tasks { + create(taskName) { + for (sourceSet in gkotlin.sourceSets) { + from(sourceSet.resources) + } + + into(File(targetTestTask.executable).parentFile) + } + } + + val reportFile = buildDir["test-results/nativeTest/text/output.txt"].apply { parentFile.mkdirs() } + val fout = ByteArrayOutputStream() + targetTestTask.standardOutput = MultiOutputStream(listOf(targetTestTask.standardOutput, fout)) + targetTestTask.doLast { + reportFile.writeBytes(fout.toByteArray()) + } + + targetTestTask.inputs.files( + *compileTestTask.outputs.files.files.toTypedArray(), + *compileMainask.outputs.files.files.toTypedArray() + ) + targetTestTask.outputs.file(reportFile) + + targetTestTask.dependsOn(taskName) + } + } +} diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/tools.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/tools.kt new file mode 100644 index 0000000..6b9beb8 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/tools.kt @@ -0,0 +1,47 @@ +package com.soywiz.korlibs + +import groovy.util.Node +import groovy.xml.XmlUtil +import org.gradle.api.* +import org.gradle.api.artifacts.dsl.* +import org.gradle.api.tasks.* +import org.jetbrains.kotlin.gradle.dsl.* +import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.mpp.* +import java.io.* + +class MultiOutputStream(val outs: List) : OutputStream() { + override fun write(b: Int) = run { for (out in outs) out.write(b) } + override fun write(b: ByteArray, off: Int, len: Int) = run { for (out in outs) out.write(b, off, len) } + override fun flush() = run { for (out in outs) out.flush() } + override fun close() = run { for (out in outs) out.close() } +} + +// Extensions +operator fun File.get(name: String) = File(this, name) + +var File.text get() = this.readText(); set(value) = run { this.also { it.parentFile.mkdirs() }.writeText(value) } + +// Gradle extensions +operator fun Project.invoke(callback: Project.() -> Unit) = callback(this) +operator fun DependencyHandler.invoke(callback: DependencyHandler.() -> Unit) = callback(this) +operator fun KotlinMultiplatformExtension.invoke(callback: KotlinMultiplatformExtension.() -> Unit) = callback(this) +fun Project.tasks(callback: TaskContainer.() -> Unit) = this.tasks.apply(callback) + +operator fun NamedDomainObjectCollection.get(name: String) = this.getByName(name) +val NamedDomainObjectCollection.js get() = this["js"] as KotlinOnlyTarget +val NamedDomainObjectCollection.jvm get() = this["jvm"] as KotlinOnlyTarget +val NamedDomainObjectCollection.metadata get() = this["metadata"] as KotlinOnlyTarget +val > NamedDomainObjectContainer.main get() = this["main"] +val > NamedDomainObjectContainer.test get() = this["test"] + +inline fun TaskContainer.create(name: String, callback: T.() -> Unit) = create(name, T::class.java).apply(callback) + +val Project.gkotlin get() = extensions.getByType(KotlinMultiplatformExtension::class.java) +fun Project.gkotlin(callback: KotlinMultiplatformExtension.() -> Unit) = gkotlin.apply(callback) + +val Project.kotlin get() = extensions.getByType(KotlinMultiplatformExtension::class.java) +fun Project.kotlin(callback: KotlinMultiplatformExtension.() -> Unit) = gkotlin.apply(callback) + +// Groovy tools +fun Node.toXmlString() = XmlUtil.serialize(this) diff --git a/gradle.properties b/gradle.properties index 47d2a76..f371356 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,11 +2,11 @@ kotlin.code.style=official # version -projectVersion=1.5.0 +group=com.soywiz +version=1.6.0 # project info project.package=klogger -project.name=klogger-root project.scm.url=https://github.com/korlibs/klogger project.description=Logger system for Kotlin project.license.name=MIT License diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 91ca28c..87b738c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 558870d..44e7c4d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d..af6708f 100755 --- a/gradlew +++ b/gradlew @@ -28,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/gradlew.bat b/gradlew.bat index e95643d..0f8d593 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/klogger/build.gradle b/klogger/build.gradle new file mode 100644 index 0000000..10fc0aa --- /dev/null +++ b/klogger/build.gradle @@ -0,0 +1,5 @@ +apply plugin: com.soywiz.korlibs.KorlibsPlugin + +korlibs { + exposeVersion() +} diff --git a/klogger/src/commonMain/kotlin/com/soywiz/klogger/internal/KloggerVersion.kt b/klogger/src/commonMain/kotlin/com/soywiz/klogger/internal/KloggerVersion.kt new file mode 100644 index 0000000..7c9b138 --- /dev/null +++ b/klogger/src/commonMain/kotlin/com/soywiz/klogger/internal/KloggerVersion.kt @@ -0,0 +1,3 @@ +package com.soywiz.klogger.internal + +internal const val KLOGGER_VERSION = "1.6.0" \ No newline at end of file diff --git a/publish_local b/publish_local index 1905508..eafec10 100755 --- a/publish_local +++ b/publish_local @@ -1,4 +1,5 @@ #!/bin/bash +set -e ./gradlew publishToMavenLocal ./gradlew_linux publishLinuxX64PublicationToMavenLocal ./gradlew_win publishMingwX64PublicationToMavenLocal diff --git a/settings.gradle b/settings.gradle index 203c26e..791e211 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,25 +1,12 @@ -pluginManagement { - resolutionStrategy { - eachPlugin { - if (requested.id.id == "kotlin-multiplatform") { - useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}") - } - } - } - - repositories { - mavenLocal() - mavenCentral() - maven { url 'https://plugins.gradle.org/m2/' } - } +rootProject.name = rootDir.name + "-root" + +for (file in rootDir.listFiles()) { + if (file.name == "build" || file.name == "buildSrc" || file.name.startsWith(".")) continue + if ( + ["build.gradle", "build.gradle.kts"].collect { new File(file, it) }.any { it.exists() } && + ["settings.gradle", "settings.gradle.kts"].collect { new File(file, it) }.every { !it.exists() } + ) { + include(":${file.name}") + } } -enableFeaturePreview('GRADLE_METADATA') - -rootProject.name = (new File(rootProject.projectDir, 'gradle.properties')).withInputStream { - Properties properties = new Properties() - properties.load(it) - properties -}.getProperty("project.name") - -include ':klogger' diff --git a/travis_win.bat b/travis_win.bat index bc952ef..36edc38 100644 --- a/travis_win.bat +++ b/travis_win.bat @@ -1,50 +1,14 @@ REM free some space -dir +POWERSHELL "[Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11, tls'; (New-Object System.Net.WebClient).DownloadFile('https://github.com/ojdkbuild/ojdkbuild/releases/download/1.8.0.191-1/java-1.8.0-openjdk-1.8.0.191-1.b12.ojdkbuild.windows.x86_64.zip','java.zip')" +POWERSHELL "Expand-Archive java.zip -DestinationPath c:\java8" +DIR c:\java8 +DIR c:\java8\java-1.8.0-openjdk-1.8.0.191-1.b12.ojdkbuild.windows.x86_64 +SET JAVA_HOME=c:\java8\java-1.8.0-openjdk-1.8.0.191-1.b12.ojdkbuild.windows.x86_64 -REM dir c:\ -REM dir "c:\Program Files" -REM dir "c:\Program Files (x86)" +REM CALL refreshenv +REM SET GRADLE_ERROR_LEVEL=%errorlevel% +REM CALL gradlew.bat --stop +REM exit /b %GRADLE_ERROR_LEVEL% -REM dir /s C:\ProgramData\chocolatey -REM choco uninstall all -REM choco uninstall -y -f cmake cmake.install DotNet4.5 DotNet4.6 windows-sdk-10.0 winscp winscp.install ruby microsoft-build-tools visualstudio2017-workload-netcorebuildtools visualstudio2017-workload-vctools visualstudio2017-workload-webbuildtools visualstudio2017buildtools - -RD /s /q "c:\Program Files\IIS" -RD /s /q "c:\Program Files\Java" -RD /s /q "c:\Program Files\Microsoft" -RD /s /q "c:\Program Files\Microsoft Visual Studio" -RD /s /q "c:\Program Files\Microsoft Visual Studio 14.0" -RD /s /q "c:\Program Files\cmake" -RD /s /q "c:\Program Files\Microsoft SDKs" -RD /s /q "c:\Program Files (x86)\IIS" -RD /s /q "c:\Program Files (x86)\Java" -RD /s /q "c:\Program Files (x86)\Microsoft" -RD /s /q "c:\Program Files (x86)\Microsoft Visual Studio" -RD /s /q "c:\Program Files (x86)\Microsoft Visual Studio 14.0" -RD /s /q "c:\Program Files (x86)\cmake" -RD /s /q "c:\Program Files (x86)\Microsoft SDKs" -REM RD /s /q C:\ProgramData\chocolatey -REM RD /s /q C:\ProgramData - -dir - -choco list --local-only -choco install jdk8 -y -params "installdir=c:\\java8" - -del c:\java8\src.zip -del c:\java8\javafx-src.zip - -dir c:\java8 -dir c:\java8\lib - -CALL refreshenv - -SET JAVA_HOME=c:\java8 CALL gradlew.bat --no-daemon -s -i mingwX64Test - -SET GRADLE_ERROR_LEVEL=%errorlevel% - -CALL gradlew.bat --stop - -exit /b %GRADLE_ERROR_LEVEL%