blob: cab63241866f7580409c7826ad6c77e741acc963 [file] [log] [blame]
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"
}