Unverified Commit bee202e5 authored by Alexey Tsvetkov's avatar Alexey Tsvetkov Committed by GitHub

Merge pull request #7 from JetBrains/rr/all-gradle

CI publishing for all platforms
parents 27491cd8 bb303bd1
...@@ -2,10 +2,48 @@ ...@@ -2,10 +2,48 @@
## Building JVM bindings ## Building JVM bindings
* Download or build Skia for your target platform (see https://bintray.com/beta/#/jetbrains/skija/Skia?tab=files) * (Optional) Set SKIA_DIR to location of Skia (binaries can be downloaded
* Set SKIA_DIR to location of Skia [here](https://bintray.com/beta/#/jetbrains/skija/Skia?tab=files))
* Set JAVA_HOME to location of JDK, at least version 11 * Set JAVA_HOME to location of JDK, at least version 11
* Run `build.sh` at least once to properly set up Skija * `cd skiko && ./gradlew publishToMavenLocal` will build the artefact and publish it to local Maven repo
* If Skija repo is updated - run `build.sh` again
* `cd skiko && ./gradlew publishToMavenLocal` will build the artefact and publish it to local Maven repo
#### Working with Skia or Skija sources
Gradle build downloads the necessary version of Skia & Skija by default.
However, if downloaded sources are modified, changes are discarded (Gradle
re-evaluates tasks, when outputs are changed).
To use custom version of the dependencies, specify `SKIA_DIR` or `SKIJA_DIR` environment variable
respectively.
#### Building on Windows
##### Using Visual Studio C++
* Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) or
[Visual Studio C++](https://visualstudio.microsoft.com/vs/features/cplusplus/).
* If Gradle fails to find Visual C++ toolchain:
```
Execution failed for task ':compileDebugWindowsCpp'.
> No tool chain is available to build C++ for host operating system 'Windows 10' architecture 'x86-64':
- Tool chain 'visualCpp' (Visual Studio):
- Could not locate a Visual Studio installation, using the command line tool, Windows registry or system path.
```
set `SKIKO_VSBT_PATH` environment variable to the location of installed Visual Studio Build Tools.
This could be done in the UI:
```
Control Panel|All Control Panel Items|System|Advanced system settings|Environment variables
```
or by running `cmd` as administrator:
```
setx /M SKIKO_VSBT_PATH "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools"
```
#### Releasing new version of Skiko
0. Check all necessary changes are published to the repository.
1. Trigger a new deployment in [Publish release](https://teamcity.jetbrains.com/buildConfiguration/JetBrainsPublicProjects_Skija_Skiko_PublishRelease)
build configuration.
1. Click "Deploy" button.
2. Specify the desired version in "Skiko Release Version" text field on the "Parameters" tab.
3. Choose the desired branch and commit on the "Changes" tab.
4. Optionally you can check "Put the build to the queue top" option in the "General" tab to speed up a deployment
(please be mindful about it!).
\ No newline at end of file
#!/bin/bash
./preBuild.sh
cd skiko && ./gradlew publishToMavenLocal
#!/bin/bash
if [ ! -d ./skija ]; then
git clone https://github.com/JetBrains/skija.git
pushd ./skija
else
pushd ./skija && git pull
fi
git checkout c3faf18878a0ad3244e4119a69b555b5b77a21d0
popd
SEP=:
if [ ! -z `uname | grep MINGW` ]; then
SEP=\;
fi
java -jar ./libs/lombok.jar delombok skija/src/main/java -d skiko/src/jvmMain/java \
--classpath=./libs/annotations-19.0.0.jar${SEP}./libs/lombok.jar
...@@ -2,3 +2,4 @@ build ...@@ -2,3 +2,4 @@ build
.gradle .gradle
local.properties local.properties
.DS_Store .DS_Store
dependencies/
import de.undercouch.gradle.tasks.download.Download
import kotlin.text.capitalize import kotlin.text.capitalize
import org.gradle.crypto.checksum.Checksum import org.gradle.crypto.checksum.Checksum
...@@ -6,16 +7,17 @@ plugins { ...@@ -6,16 +7,17 @@ plugins {
`cpp-library` `cpp-library`
`maven-publish` `maven-publish`
id("org.gradle.crypto.checksum") version "1.1.0" id("org.gradle.crypto.checksum") version "1.1.0"
id("de.undercouch.download") version "4.1.1"
} }
val isCIBuild = project.hasProperty("teamcity") val properties = SkikoProperties(rootProject)
group = "org.jetbrains.skiko" group = "org.jetbrains.skiko"
version = when { version = run {
isCIBuild -> project.property("deploy.ci.version") as String val suffix = if (properties.isRelease) "" else "-SNAPSHOT"
else -> project.property("deploy.version") as String properties.deployVersion + suffix
} }
val skiaDir = System.getenv("SKIA_DIR") ?: System.getProperty("skia.dir") ?: "PLEASE_SET_SKIA_DIR"
val hostOs = System.getProperty("os.name") val hostOs = System.getProperty("os.name")
val target = when { val target = when {
hostOs == "Mac OS X" -> "macos" hostOs == "Mac OS X" -> "macos"
...@@ -32,6 +34,121 @@ repositories { ...@@ -32,6 +34,121 @@ repositories {
url = uri("https://dl.bintray.com/kotlin/kotlin-eap") url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
} }
} }
val skiaZip = run {
val zipName = properties.skiaReleaseForCurrentOS + ".zip"
val zipFile = properties.dependenciesDir.resolve("skia/$zipName")
tasks.register("downloadSkia", Download::class) {
onlyIf { properties.skiaDir == null && !zipFile.exists() }
inputs.property("skia.release.for.current.os", properties.skiaReleaseForCurrentOS)
src("https://bintray.com/api/ui/download/jetbrains/skija/$zipName")
dest(zipFile)
onlyIfModified(true)
}.map { zipFile }
}
fun String.insertAfterFirst(substring: String, stringToInsert: String): String =
let { orig ->
buildString {
var i = orig.indexOf(substring)
if (i < 0) return orig
i += substring.length
append(orig.substring(0, i))
append(stringToInsert)
append(orig.substring(i))
}
}
fun AbstractCopyTask.configureSkiaCopy(targetDir: File) {
into(targetDir)
if (target == "windows") {
doLast {
// temporary hack
// todo: remove after https://github.com/google/skia/commit/0d6f81593b1fa222e8e4afb56cc961ce8c9be375 is included
// in used version of skia
val skPathRef = targetDir.resolve("include/private/SkPathRef.h")
val skPathRefContent = skPathRef.readText()
if ("#include <tuple>" !in skPathRefContent) {
val includeToInsertAfter = "#include <limits>"
check(includeToInsertAfter in skPathRefContent) { "Substring not found: '${includeToInsertAfter}' in $skPathRef" }
val newContent = skPathRefContent.insertAfterFirst(includeToInsertAfter, "\n#include <tuple>")
skPathRef.writeText(newContent)
}
}
}
}
val skiaDir = run {
if (properties.skiaDir != null) {
tasks.register("skiaDir", DefaultTask::class) {
// dummy task to simplify usage of the resulting provider (see `else` branch)
// if a file provider is not created from a task provider,
// then it cannot be used instead of a task in `dependsOn` clauses of other tasks.
// e.g. the resulting `skiaDir` could not be used in `dependsOn` of CppCompile configuration
enabled = false
}.map { properties.skiaDir!! }
} else {
val targetDir = properties.dependenciesDir.resolve("skia/skia")
tasks.register("unzipSkia", Copy::class) {
from(skiaZip.map { zipTree(it) })
configureSkiaCopy(targetDir)
}.map { targetDir }
}
}
val skijaZip = run {
val zipFile = properties.dependenciesDir.resolve("skija/${properties.skijaCommitHash}.zip")
tasks.register("downloadSkija", Download::class) {
onlyIf { properties.skijaDir == null && !zipFile.exists() }
inputs.property("skija.commit.hash", properties.skijaCommitHash)
src("https://github.com/JetBrains/skija/archive/${properties.skijaCommitHash}.zip")
dest(zipFile)
onlyIfModified(true)
}.map { zipFile }
}
val skijaDir = run {
if (properties.skijaDir != null) {
tasks.register("skijaDir", DefaultTask::class) {
enabled = false
}.map { properties.skijaDir!! }
} else {
val skijaDest = properties.dependenciesDir.resolve("skija/skija").apply { mkdirs() }
tasks.register("unzipSkija", Copy::class) {
from(skijaZip.map { zipTree(it) }) {
include("skija-${properties.skijaCommitHash}/**")
eachFile {
// drop skija-<COMMIT> subdir
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray())
}
includeEmptyDirs = false
}
into(skijaDest)
}.map { skijaDest }
}
}
val lombok by configurations.creating
val jetbrainsAnnotations by configurations.creating
dependencies {
lombok("org.projectlombok:lombok:1.18.12")
jetbrainsAnnotations("org.jetbrains:annotations:19.0.0")
}
val skijaSrcDir = run {
val delombokSkijaSrcDir = project.file("src/jvmMain/java")
tasks.register("delombokSkija", JavaExec::class) {
classpath = lombok + jetbrainsAnnotations
main = "lombok.launch.Main"
args("delombok", skijaDir.get().resolve("src/main/java"), "-d", delombokSkijaSrcDir)
inputs.dir(skijaDir)
outputs.dirs(delombokSkijaSrcDir)
}.map { delombokSkijaSrcDir }
}
kotlin { kotlin {
jvm { jvm {
compilations.all { compilations.all {
...@@ -61,11 +178,11 @@ kotlin { ...@@ -61,11 +178,11 @@ kotlin {
} }
} }
val jvmMain by getting { val jvmMain by getting {
//kotlin.srcDirs.add(file("$projectDir/../skija/java_delombok")) kotlin.srcDirs(skijaSrcDir)
dependencies { dependencies {
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
compileOnly("org.projectlombok:lombok:1.18.12") compileOnly(lombok)
compileOnly("org.jetbrains:annotations:19.0.0") compileOnly(jetbrainsAnnotations)
} }
} }
...@@ -92,6 +209,8 @@ tasks.withType(CppCompile::class.java).configureEach { ...@@ -92,6 +209,8 @@ tasks.withType(CppCompile::class.java).configureEach {
"Check JAVA_HOME (CLI) or Gradle settings (Intellij).") "Check JAVA_HOME (CLI) or Gradle settings (Intellij).")
} }
val jdkHome = System.getProperty("java.home") ?: error("'java.home' is null") val jdkHome = System.getProperty("java.home") ?: error("'java.home' is null")
dependsOn(skiaDir)
val skiaDir = skiaDir.get().absolutePath
compilerArgs.addAll(listOf( compilerArgs.addAll(listOf(
"-I$jdkHome/include", "-I$jdkHome/include",
"-I$skiaDir", "-I$skiaDir",
...@@ -219,7 +338,7 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach { ...@@ -219,7 +338,7 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
extensions.configure<CppLibrary> { extensions.configure<CppLibrary> {
source.from( source.from(
fileTree("$projectDir/../skija/src/main/cc"), skijaDir.map { fileTree(it.resolve("src/main/cc")) },
fileTree("$projectDir/src/jvmMain/cpp/common"), fileTree("$projectDir/src/jvmMain/cpp/common"),
fileTree("$projectDir/src/jvmMain/cpp/$target") fileTree("$projectDir/src/jvmMain/cpp/$target")
) )
...@@ -231,16 +350,26 @@ library { ...@@ -231,16 +350,26 @@ library {
baseName.set("skiko") baseName.set("skiko")
dependencies { dependencies {
implementation(fileTree("$skiaDir/out/Release-x64").matching { implementation(
if (target == "windows") skiaDir.map {
include("**.lib") fileTree(it.resolve("out/Release-x64"))
else .matching { include(if (target == "windows") "**.lib" else "**.a") }
include("**.a") }
}) )
implementation(fileTree("$buildDir/objc/$target").matching { implementation(fileTree("$buildDir/objc/$target").matching {
include("**.o") include("**.o")
}) })
} }
toolChains {
withType(VisualCpp::class.java) {
// In some cases Gradle is unable to find VC++ toolchain
// https://github.com/gradle/gradle-native/issues/617
properties.visualStudioBuildToolsDir?.let {
setInstallDir(it)
}
}
}
} }
val skikoJvmJar: Provider<Jar> by tasks.registering(Jar::class) { val skikoJvmJar: Provider<Jar> by tasks.registering(Jar::class) {
...@@ -252,7 +381,7 @@ val createChecksums by project.tasks.registering(org.gradle.crypto.checksum.Chec ...@@ -252,7 +381,7 @@ val createChecksums by project.tasks.registering(org.gradle.crypto.checksum.Chec
val linkTask = project.tasks.named("linkRelease${target.capitalize()}") val linkTask = project.tasks.named("linkRelease${target.capitalize()}")
dependsOn(linkTask) dependsOn(linkTask)
files = linkTask.get().outputs.files.filter { it.isFile } + files = linkTask.get().outputs.files.filter { it.isFile } +
if (target == "windows") files("$skiaDir/out/Release-x64/icudtl.dat") else files() if (target == "windows") files(skiaDir.map { it.resolve("out/Release-x64/icudtl.dat") }) else files()
algorithm = Checksum.Algorithm.SHA256 algorithm = Checksum.Algorithm.SHA256
outputDir = file("$buildDir/checksums") outputDir = file("$buildDir/checksums")
} }
...@@ -265,7 +394,7 @@ val skikoJvmRuntimeJar by project.tasks.registering(Jar::class) { ...@@ -265,7 +394,7 @@ val skikoJvmRuntimeJar by project.tasks.registering(Jar::class) {
it.outputs.files.filter { it.isFile } it.outputs.files.filter { it.isFile }
}) })
if (target == "windows") { if (target == "windows") {
from(files("$skiaDir/out/Release-x64/icudtl.dat")) from(files(skiaDir.map { it.resolve("out/Release-x64/icudtl.dat") }))
} }
from(createChecksums.get().outputs.files) from(createChecksums.get().outputs.files)
} }
...@@ -374,3 +503,32 @@ publishing { ...@@ -374,3 +503,32 @@ publishing {
} }
} }
} }
class SkikoProperties(private val myProject: Project) {
val isCIBuild: Boolean
get() = myProject.hasProperty("teamcity")
val deployVersion: String
get() = myProject.property("deploy.version") as String
val isRelease: Boolean
get() = myProject.findProperty("deploy.release") == "true"
val skijaCommitHash: String
get() = myProject.property("dependencies.skija.git.commit") as String
val skiaReleaseForCurrentOS: String
get() = (myProject.property("dependencies.skia.$target") as String)
val visualStudioBuildToolsDir: File?
get() = System.getenv()["SKIKO_VSBT_PATH"]?.let { File(it) }?.takeIf { it.isDirectory }
val skijaDir: File?
get() = System.getenv()["SKIJA_DIR"]?.let { File(it) }?.takeIf { it.isDirectory }
val skiaDir: File?
get() = (System.getenv()["SKIA_DIR"] ?: System.getProperty("skia.dir"))?.let { File(it) }?.takeIf { it.isDirectory }
val dependenciesDir: File
get() = myProject.rootProject.projectDir.resolve("dependencies")
}
kotlin.code.style=official kotlin.code.style=official
deploy.version=0.1-SNAPSHOT deploy.version=0.1
deploy.ci.version=0.1 dependencies.skija.git.commit=c3faf18878a0ad3244e4119a69b555b5b77a21d0
deploy.version=0.1-SNAPSHOT dependencies.skia.windows= Skia-m85-windows-Release-x64
deploy.ci.version=0.1 dependencies.skia.linux=Skia-m85-linux-Release-x64
\ No newline at end of file dependencies.skia.macos=Skia-85-macos-Release-x64
\ No newline at end of file
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment