Files
kotlin-fork/libraries/stdlib/js-v1/build.gradle
T
Ilya Gorbunov b59f668a50 Change the way kotlin.js source map paths are postprocessed
The idea is that we do no longer use `sourceMapBaseDirs` parameter
of `compileKotlin2Js` task to remove prefix from source paths,
but instead preserve the full paths relative to the output directory.
This allows us to avoid duplicate file names and to identify
source files more reliably.
Then, after sources have been embedded in the source map, we remove
several relative prefixes from source paths.
2021-04-26 13:13:21 +03:00

381 lines
11 KiB
Groovy

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")
testCompile 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 "Iterators.kt"
include "Range.kt"
include "Progressions.kt"
include "ProgressionIterators.kt"
include "Ranges.kt"
include "internal/InternalAnnotations.kt"
include "internal/progressionUtil.kt"
include "Unit.kt"
}
into builtinsSrcDir
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile) {
kotlinOptions {
main = "noCall"
moduleKind = "commonjs"
freeCompilerArgs = [
"-version",
"-Xallow-kotlin-package",
"-Xallow-result-return-type"
]
}
}
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 += [
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlin.ExperimentalMultiplatform",
"-Xopt-in=kotlin.contracts.ExperimentalContracts",
"-Xinline-classes"
]
}
}
compileTestKotlin2Js {
kotlinOptions {
moduleKind = "umd"
freeCompilerArgs += [
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlin.ExperimentalUnsignedTypes",
"-Xopt-in=kotlin.ExperimentalStdlibApi",
]
}
}
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'
}
main = "org.jetbrains.kotlin.cli.js.internal.JSStdlibLinker"
// local variables for configuration cache work
def rootDir = rootDir
def projectDir = projectDir
def compileBuiltinsKotlin2JsFiles = compileBuiltinsKotlin2Js.outputs.files
def compileKotlin2JsFiles = compileKotlin2Js.outputs.files
doFirst {
args = [jsOutputFileName, rootDir, "$jsSrcDir/wrapper.js"] + inputFiles.collect { it.path }.sort() +
(compileBuiltinsKotlin2JsFiles.collect { it.path }.sort() +
compileKotlin2JsFiles.collect { it.path }.sort()).findAll {
it.endsWith(".js") && !it.endsWith(".meta.js")
}
}
classpath = configurations.kotlinCompilerClasspath
def sourceMapFile = file(jsOutputMapFileName)
def jsOutputMetaFile = file(jsOutputMetaFileName)
def compileMetaFile = file(compileKotlin2Js.outputFile.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.output
filesMatching("*.*") { it.mode = 0b110100100 } // KTI-401
}
task libraryJarWithIr(type: Zip, dependsOn: libraryJarWithoutIr) {
archiveExtension = "jar"
destinationDirectory = file("$buildDir/libs")
duplicatesStrategy DuplicatesStrategy.FAIL
from zipTree(libraryJarWithoutIr.archiveFile)
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) {
archiveClassifier.set('sources')
includeEmptyDirs false
duplicatesStrategy = DuplicatesStrategy.FAIL
from("${builtinsDir}/native/kotlin") {
into 'kotlin'
include 'Comparable.kt'
include 'Enum.kt'
}
from(sourceSets.main.allSource) {
into 'kotlin'
exclude '**/*.java'
exclude 'org.w3c/**'
exclude 'js/**'
}
from(sourceSets.main.allSource) {
include 'org.w3c/**'
}
}
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 {
runtime libraryJarWithIr
publishedRuntime libraryJarWithIr
publishedRuntime sourcesJar
sources sourcesJar
distSources distSourcesJar
distLibrary libraryJarWithIr
compileJs.outputs.files.forEach { artifact ->
distJs(artifact) { builtBy(compileJs) }
}
}
node {
download = true
version = '12.18.0'
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