blob: e29bfe7667dc6d1124a6c40f520f8123b42b717f [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.android.build.api.attributes.BuildTypeAttr
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.Usage
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import static androidx.build.dependencies.DependenciesKt.*
plugins {
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXUiPlugin")
id("kotlin-multiplatform")
}
repositories {
// To allow using local Skija build.
mavenLocal()
}
configurations {
ui_components
compose_compiler_jar
}
AttributeContainer attrContainer = configurations.ui_components.getAttributes();
attrContainer.attribute(
BuildTypeAttr.ATTRIBUTE,project.getObjects().named(BuildTypeAttr.class, "release")
)
attrContainer.attribute(
Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME)
)
attrContainer.attribute(
Attribute.of("org.jetbrains.kotlin.platform.type", KotlinPlatformType.class), KotlinPlatformType.jvm
)
dependencies {
ui_components "androidx.lifecycle:lifecycle-common:2.3.0-alpha01"
ui_components "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
ui_components "androidx.core:core:1.2.0"
ui_components "androidx.arch.core:core-common:2.1.0"
ui_components "org.jogamp.jogl:jogl-all:2.4.0-rc-20200306"
ui_components "org.jogamp.jogl:jogl-all-natives-linux-amd64:2.4.0-rc-20200306"
ui_components "org.jogamp.jogl:jogl-all-natives-macosx-universal:2.4.0-rc-20200306"
ui_components "org.jogamp.gluegen:gluegen-rt:2.4.0-rc-20200306"
ui_components "org.jogamp.gluegen:gluegen-rt-natives-linux-amd64:2.4.0-rc-20200306"
ui_components "org.jogamp.gluegen:gluegen-rt-natives-macosx-universal:2.4.0-rc-20200306"
compose_compiler_jar project(":compose:compose-compiler")
}
dependencies {
kotlinPlugin project(path: ":compose:compose-compiler")
}
def joglDir = "${project.rootDir}/ui-desktop/libs"
def androidxDir = "${project.rootDir}/ui-desktop/libs"
def composeClassDir = project.rootDir.absolutePath + "/ui-desktop/compose-libs/"
kotlin {
jvm()
sourceSets {
commonMain.dependencies {
api(KOTLIN_STDLIB_COMMON)
implementation project(":compose:compose-runtime")
}
jvmMain {
}
jvmMain.dependencies {
api(KOTLIN_STDLIB)
api(KOTLIN_COROUTINES_CORE)
api "org.jetbrains.skija:skija:0.1.0"
api project(":ui:ui-desktop:android-emu")
api files("$joglDir/gluegen-rt.jar")
api files("$joglDir/jogl-all.jar")
api fileTree(project.rootDir.absolutePath + "/ui-desktop/compose-libs")
implementation files("$androidxDir/core-common-2.1.0.jar")
implementation "androidx.lifecycle:lifecycle-common:2.3.0-alpha01"
implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
implementation files("$joglDir/gluegen-rt-natives-macosx-universal.jar")
implementation files("$joglDir/jogl-all-natives-macosx-universal.jar")
// TODO: this is a bit ugly. We introduce dependency here, but in fact
// manually copy it later, as run task will have .aar in the classpath.
implementation "androidx.core:core:1.0.0"
implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
}
}
}
def uiComponents = [
"ui-android-view",
"ui-animation",
"ui-animation-core",
"ui-core",
"ui-foundation",
"ui-framework",
"ui-geometry",
"ui-graphics",
"ui-layout",
"ui-livedata",
"ui-material",
"ui-platform",
"ui-saved-instance-state",
"ui-test",
"ui-text",
"ui-text-android",
"ui-text-core",
"ui-tooling",
"ui-unit",
"ui-util",
"ui-vector"
]
def androidxComponents = [
"core:core",
"lifecycle:lifecycle-runtime"
]
def copyToJar(File source, File jar) {
if(source.name.endsWith(".jar")) {
Files.copy(source.toPath(), jar.toPath(), StandardCopyOption.REPLACE_EXISTING)
return
}
byte[] buffer = new byte[2048]
FileInputStream fis = new FileInputStream(source)
BufferedInputStream bis = new BufferedInputStream(fis)
ZipInputStream stream = new ZipInputStream(bis)
ZipEntry entry = null
while ((entry = stream.getNextEntry()) != null) {
if(!entry.name.equals("classes.jar")) continue;
FileOutputStream fos = new FileOutputStream(jar)
BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.size())
int len = 0
while ((len = stream.read(buffer)) > 0) {
bos.write(buffer, 0, len)
}
bos.close()
fos.close()
}
stream.close()
bis.close()
fis.close()
}
// Find in dependencies first (BFS) task's output ending with `name`.
String findInDeps(Task root, String name) {
// Do BFS by deps.
def queue = new java.util.ArrayDeque<Task>()
queue.addLast(root)
while (queue.size() > 0) {
def task = queue.pop()
def classes = task.outputs.files.files.find { it.name.endsWith(name) }
if (classes != null) {
return classes.absolutePath
}
task.taskDependencies.getDependencies(task).each {
queue.addLast(it)
}
}
return null
}
task extractJars {
doLast {
// Find all JAR files matching components.
file(composeClassDir).mkdir()
uiComponents.each { component ->
def depProject = project(":ui:" + component)
def task = depProject.tasks.named("assemble").get()
def srcJar = findInDeps(task, "classes.jar")
if (srcJar == null) {
throw new Error("cannot find classes.jar in "+ task)
} else {
def destJar = composeClassDir + component + ".jar"
Files.copy(Paths.get(srcJar), Paths.get(destJar), StandardCopyOption.REPLACE_EXISTING)
}
}
def frameworkProject = project(":ui:ui-framework")
def srcJar = findInDeps(frameworkProject.tasks.named("assemble").get(), "compose-compiler.jar")
if (srcJar == null)
throw new Error("cannot find compose-compiler.jar")
Files.copy(Paths.get(srcJar),
Paths.get(composeClassDir + "compose-compiler.jar"), StandardCopyOption.REPLACE_EXISTING)
configurations.ui_components.getIncoming().artifactView(
{ config ->
config.attributes({container ->
// ... container.attribute(Attribute.of("artifactType", String.class), "android-classes")
})
})
.getArtifacts().getArtifactFiles().each { component ->
copyToJar(
component,
Paths.get(composeClassDir + component.name+".jar").toFile()
)
};
}
}
extractJars.configure {
uiComponents.each { component ->
extractJars.dependsOn(":ui:" + component + ":assemble")
}
}
tasks.withType(KotlinCompile).configureEach {
dependsOn("extractJars")
kotlinOptions {
useIR = true
freeCompilerArgs += [
// TODO: hack, apply compose plugin better.
"-Xplugin=${project.rootDir.absolutePath}/ui-desktop/compose-libs/compose-compiler.jar",
"-P", "plugin:androidx.compose.plugins.idea:enabled=true",
]
}
}
task run(type: JavaExec) {
main = 'androidx.ui.desktop.example.MainKt'
def compilation = kotlin.jvm().compilations["main"]
classpath = compilation.output.allOutputs + compilation.runtimeDependencyFiles +
fileTree(composeClassDir)
}