| plugins { |
| id "com.github.node-gradle.node" version "3.0.1" |
| } |
| |
| description = 'Kotlin Standard Library for JS' |
| |
| apply plugin: 'kotlin-platform-js' |
| apply plugin: 'idea' |
| |
| configurePublishing(project) |
| configureJavadocJar() |
| |
| configurations { |
| sources |
| commonSources |
| distSources |
| distJs |
| distLibrary |
| } |
| |
| def builtinsSrcDir = "${buildDir}/builtin-sources" |
| def builtinsSrcDir2 = "${buildDir}/builtin-sources-for-builtins" |
| def jsCommonDir = "${projectDir}/../js" |
| |
| def builtinsDir = "${rootDir}/core/builtins" |
| |
| def jsSrcDir = "src" |
| def jsCommonSrcDir = "${jsCommonDir}/src" |
| def jsTestSrcDir = "test" |
| def jsCommonTestSrcDir = "${jsCommonDir}/test" |
| |
| def jsSrcJsDir = "${jsSrcDir}/js" |
| def jsOutputFileName = "${buildDir}/classes/kotlin.js" |
| def jsOutputMapFileName = "${jsOutputFileName}.map" |
| def jsOutputMetaFileName = "${buildDir}/classes/kotlin.meta.js" |
| |
| def kotlinTestJsOutputFile = "${project(':kotlin-test:kotlin-test-js').buildDir}/classes/main/kotlin-test.js" |
| |
| // TODO: take from sourcesets' outputs |
| def jsTestOutputFile = "${buildDir}/classes/kotlin/test/kotlin-stdlib-js_test.js" |
| def kotlinTestJsTestOutputFile = "${project(':kotlin-test:kotlin-test-js').buildDir}/classes/kotlin/test/kotlin-test-js_test.js" |
| |
| sourceSets { |
| builtins { |
| kotlin { |
| srcDir builtinsSrcDir2 |
| srcDir "${jsCommonDir}/runtime" |
| srcDir 'runtime' |
| } |
| } |
| |
| main { |
| kotlin { |
| srcDir builtinsSrcDir |
| srcDir jsCommonSrcDir |
| srcDir jsSrcDir |
| } |
| } |
| |
| test { |
| kotlin { |
| srcDir jsTestSrcDir |
| srcDir jsCommonTestSrcDir |
| } |
| } |
| } |
| |
| dependencies { |
| expectedBy project(":kotlin-stdlib-common") |
| commonSources project(path: ":kotlin-stdlib-common", configuration: "sources") |
| testApi project(':kotlin-test:kotlin-test-js') |
| } |
| |
| task prepareComparableSource(type: Copy) { |
| def fs = services.get(FileSystemOperations) |
| doFirst { |
| fs.delete { |
| delete builtinsSrcDir2 |
| } |
| } |
| from("${builtinsDir}/native/kotlin") { |
| include "Comparable.kt" |
| } |
| into builtinsSrcDir2 |
| } |
| |
| task prepareBuiltinsSources(type: Copy) { |
| def fs = services.get(FileSystemOperations) |
| doFirst { |
| fs.delete { |
| delete builtinsSrcDir |
| } |
| } |
| from("${builtinsDir}/native/kotlin") { |
| include "Iterator.kt" |
| include "Collections.kt" |
| include "CharSequence.kt" |
| include "Annotation.kt" |
| } |
| from("${builtinsDir}/src/kotlin/") { |
| include "annotation/Annotations.kt" |
| include "Function.kt" |
| include "Unit.kt" |
| } |
| into builtinsSrcDir |
| } |
| |
| tasks.withType(org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile) { |
| kotlinOptions { |
| main = "noCall" |
| moduleKind = "commonjs" |
| freeCompilerArgs = [ |
| "-Xallow-kotlin-package", |
| ] |
| } |
| } |
| |
| compileBuiltinsKotlin2Js { |
| dependsOn prepareComparableSource |
| kotlinOptions { |
| metaInfo = false |
| outputFile = "${buildDir}/classes/builtins/kotlin.js" |
| sourceMap = true |
| sourceMapPrefix = "./" |
| } |
| } |
| |
| compileKotlin2Js { |
| dependsOn prepareBuiltinsSources |
| kotlinOptions { |
| outputFile = "${buildDir}/classes/main/kotlin.js" |
| sourceMap = true |
| freeCompilerArgs += [ |
| "-opt-in=kotlin.RequiresOptIn", |
| "-opt-in=kotlin.ExperimentalMultiplatform", |
| "-opt-in=kotlin.contracts.ExperimentalContracts", |
| "-XXLanguage:+RangeUntilOperator", |
| "-Xforce-deprecated-legacy-compiler-usage" |
| ] |
| } |
| } |
| |
| compileTestKotlin2Js { |
| kotlinOptions { |
| moduleKind = "umd" |
| freeCompilerArgs += [ |
| "-opt-in=kotlin.RequiresOptIn", |
| "-opt-in=kotlin.ExperimentalUnsignedTypes", |
| "-opt-in=kotlin.ExperimentalStdlibApi", |
| "-opt-in=kotlin.io.encoding.ExperimentalEncodingApi", |
| "-XXLanguage:+RangeUntilOperator", |
| ] |
| } |
| } |
| |
| task compileJs(type: NoDebugJavaExec) { |
| dependsOn compileBuiltinsKotlin2Js, compileKotlin2Js |
| inputs.files(compileBuiltinsKotlin2Js.outputs.files).withPathSensitivity(PathSensitivity.RELATIVE) |
| inputs.files(compileKotlin2Js.outputs.files).withPathSensitivity(PathSensitivity.RELATIVE) |
| inputs.dir(jsSrcDir).withPathSensitivity(PathSensitivity.RELATIVE) |
| inputs.dir(jsCommonSrcDir).withPathSensitivity(PathSensitivity.RELATIVE) |
| |
| outputs.file(jsOutputFileName) |
| outputs.file(jsOutputMapFileName) |
| outputs.file(jsOutputMetaFileName) |
| outputs.cacheIf { true } |
| |
| def inputFiles = fileTree(jsSrcJsDir) { |
| include '**/*.js' |
| } |
| |
| mainClass = "org.jetbrains.kotlin.cli.js.internal.JSStdlibLinker" |
| |
| // local variables for configuration cache work |
| def rootDir = rootDir |
| def projectDir = projectDir |
| |
| def compileBuiltinsKotlin2JsFiles = compileBuiltinsKotlin2Js.destinationDirectory |
| def compileKotlin2JsFiles = compileKotlin2Js.destinationDirectory |
| doFirst { |
| args = [jsOutputFileName, rootDir, "$jsSrcDir/wrapper.js"] + inputFiles.collect { it.path }.sort() + |
| (compileBuiltinsKotlin2JsFiles.asFileTree.files.sort() + |
| compileKotlin2JsFiles.asFileTree.files.sort()).findAll { |
| it.name.endsWith(".js") && !it.name.endsWith(".meta.js") |
| } |
| } |
| classpath = configurations.kotlinCompilerClasspath |
| |
| def sourceMapFile = file(jsOutputMapFileName) |
| def jsOutputMetaFile = file(jsOutputMetaFileName) |
| def compileMetaFile = file(compileKotlin2Js.outputFileProperty.map { it.path.replaceAll('\\.js$', '.meta.js') }) |
| def mainJsOutputDir = compileKotlin2Js.destinationDirectory |
| doLast { |
| ant.replaceregexp( |
| file: jsOutputFileName, |
| match: "module.exports,\\s*require\\([^)]+\\)", |
| replace: "", |
| byline: "true", encoding: "UTF-8") |
| ant.replaceregexp( |
| file: jsOutputFileName, |
| match: "function\\s*\\(_,\\s*Kotlin\\)", |
| replace: "function()", |
| byline: "true", encoding: "UTF-8") |
| ant.replaceregexp( |
| file: jsOutputFileName, |
| match: "return\\s+_;", |
| replace: "", |
| byline: "true", encoding: "UTF-8") |
| |
| def sourceMap = new groovy.json.JsonSlurper().parseText(sourceMapFile.text) |
| |
| def sourceMapSourcesBaseDirs = [mainJsOutputDir.get(), "${jsCommonDir}/runtime", projectDir, rootDir] |
| |
| sourceMap.sourcesContent = sourceMap.sources.collect { sourceName -> |
| def text = sourceMapSourcesBaseDirs.collect { new File("$it/$sourceName") }.find { it.exists() }?.text |
| if (text == null) logger.warn("Sources missing for file $sourceName") |
| text |
| } |
| |
| def sourceMapBasePaths = [ |
| "../../../../", |
| "../../../", |
| "../../", |
| "./", |
| "libraries/stdlib/js-v1/src/" |
| ] |
| def shortPaths = sourceMap.sources.collect { sourcePath -> |
| def prefixToRemove = sourceMapBasePaths.find { basePath -> sourcePath.startsWith(basePath) } |
| if (prefixToRemove != null) sourcePath.substring(prefixToRemove.length()) else sourcePath |
| } |
| if (shortPaths.size != shortPaths.toUnique().size) { |
| logger.warn("Duplicate source file names found:\n${sourceMap.sources.toSorted().join("\n")}") |
| } |
| sourceMap.sources = shortPaths |
| |
| sourceMapFile.text = groovy.json.JsonOutput.toJson(sourceMap) |
| |
| jsOutputMetaFile.text = compileMetaFile.text |
| } |
| } |
| |
| classes.dependsOn compileJs |
| |
| |
| jar { |
| enabled false |
| } |
| |
| task libraryJarWithoutIr(type: Jar, dependsOn: compileJs) { |
| archiveClassifier = null |
| manifestAttributes(manifest, project, 'Main') |
| destinationDirectory = file("$buildDir/lib/dist") |
| |
| // TODO: Use standard implementation title after js stdlib detector becomes more flexible (KT-17655) |
| Properties properties = new Properties() |
| new File("${rootDir}/resources/kotlinManifest.properties").withInputStream { |
| properties.load(it) |
| } |
| manifest.attributes 'Implementation-Title': properties."manifest.impl.title.kotlin.javascript.stdlib" |
| |
| includeEmptyDirs false |
| duplicatesStrategy DuplicatesStrategy.EXCLUDE |
| from jsOutputFileName |
| from jsOutputMetaFileName |
| from "${jsOutputFileName}.map" |
| from sourceSets.main.kotlin.classesDirectory |
| filesMatching("*.*") { it.mode = 0b110100100 } // KTI-401 |
| } |
| |
| task libraryJarWithIr(type: Zip, dependsOn: libraryJarWithoutIr) { |
| archiveExtension = "jar" |
| destinationDirectory = file("$buildDir/libs") |
| |
| duplicatesStrategy DuplicatesStrategy.FAIL |
| |
| def archiveOperations = services.get(ArchiveOperations) |
| from { libraryJarWithoutIr.archiveFile.map {archiveOperations.zipTree(it) } } |
| dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs") |
| from { |
| def irKlib = tasks.getByPath(":kotlin-stdlib-js-ir:compileKotlinJs") |
| fileTree(irKlib.outputs.files.first().path) |
| } |
| filesMatching("*.*") { it.mode = 0b110100100 } // KTI-401 |
| } |
| |
| jar.dependsOn(libraryJarWithIr) |
| |
| task sourcesJar(type: Jar, dependsOn: compileJs) { |
| dependsOn(":kotlin-stdlib-js-ir:sourcesJar") |
| archiveClassifier.set('sources') |
| includeEmptyDirs false |
| duplicatesStrategy = DuplicatesStrategy.FAIL |
| from({ |
| def irSources = tasks.getByPath(":kotlin-stdlib-js-ir:sourcesJar") |
| zipTree(irSources.outputs.files.first().path) |
| }) { |
| exclude 'META-INF/*' |
| } |
| } |
| |
| task distSourcesJar(type: Jar) { |
| dependsOn(sourcesJar, configurations.commonSources) |
| destinationDirectory = file("$buildDir/lib/dist") |
| archiveClassifier.set('sources') |
| duplicatesStrategy = DuplicatesStrategy.FAIL |
| from zipTree(sourcesJar.outputs.files.singleFile) |
| |
| from(zipTree(configurations.commonSources.singleFile)) { |
| it.includeEmptyDirs = false |
| exclude 'META-INF/*' |
| into 'common' |
| } |
| } |
| |
| artifacts { |
| publishedRuntime libraryJarWithIr |
| publishedRuntime sourcesJar |
| sources sourcesJar |
| distSources distSourcesJar |
| distLibrary libraryJarWithIr |
| |
| compileJs.outputs.files.forEach { artifact -> |
| distJs(artifact) { builtBy(compileJs) } |
| } |
| } |
| |
| node { |
| download = true |
| version = DependenciesKt.getNodejsVersion(project) |
| nodeProjectDir = buildDir |
| } |
| |
| // Otherwise Node ignores nodeModulesDir |
| task deleteLegacyNodeModules(type: Delete) { |
| delete "$projectDir/node_modules" |
| } |
| |
| task installMocha(type: NpmTask, dependsOn: [deleteLegacyNodeModules]) { |
| args = ['install', 'mocha@8.0.1'] |
| } |
| |
| task installTeamcityReporter(type: NpmTask, dependsOn: [deleteLegacyNodeModules]) { |
| args = ['install', 'mocha-teamcity-reporter@3.0.0'] |
| } |
| |
| task runMocha(type: NodeTask, dependsOn: [testClasses, installMocha, ':kotlin-test:kotlin-test-js:testClasses']) { |
| script = file("${buildDir}/node_modules/mocha/bin/mocha") |
| |
| if (project.hasProperty("teamcity")) { |
| dependsOn installTeamcityReporter |
| args = ['--reporter', 'mocha-teamcity-reporter'] |
| } |
| else { |
| args = ['--reporter', 'min'] |
| } |
| |
| args = args.get() + ['--timeout', '10s'] |
| args = args.get() + [jsTestOutputFile, kotlinTestJsTestOutputFile] |
| |
| execOverrides { |
| it.ignoreExitValue = rootProject.ignoreTestFailures |
| it.environment('NODE_PATH', [file(jsOutputFileName).parent, file(kotlinTestJsOutputFile).parent].join(File.pathSeparator)) |
| it.workingDir = buildDir |
| } |
| } |
| |
| test.dependsOn runMocha |
| |
| tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile) { |
| kotlinOptions.freeCompilerArgs += "-Xforce-deprecated-legacy-compiler-usage" |
| } |