Skip to content

Commit

Permalink
Merge pull request #14 from usefulness/updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszkwiecinski authored Nov 12, 2023
2 parents e114486 + 8c8e202 commit f11daa7
Show file tree
Hide file tree
Showing 35 changed files with 375 additions and 242 deletions.
6 changes: 5 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ ktlint_code_style = intellij_idea
ktlint_standard_property-naming = disabled
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 2
ktlint_function_naming_ignore_when_annotated_with = Composable
ktlint_compose_unstable-collections = disabled
ktlint_compose_unstable-collections = disabled

[*.xml]
indent_size = 4
ij_xml_space_inside_empty_tag = true
79 changes: 66 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

Turn raw [cashapp/licensee](https://github.com/cashapp/licensee) report into assets/Kotlin code that can be easily consumed from an Android app

### Features
- Access licenses report directly by a generated Kotlin code (accessible via static `io.github.usefulness.licensee.Licensee` object)
- Read _licensee_ report copied to projects assets directory in runtime (via `assetManager.open("licensee_artifacts.json")`)

![example](images/generated_code_dark.png#gh-dark-mode-only)
![example](images/generated_code_light.png#gh-light-mode-only)

### Installation

Available on:
Expand All @@ -23,31 +30,77 @@ plugins {
}
```


### Features
- Access licenses report directly by a generated Kotlin code (accessible via static `io.github.usefulness.licensee.Licensee` object)
- Read _licensee_ report copied to projects assets directory in runtime (via `assetManager.open("licensee_artifacts.json")`)

### Configuration
#### Configuration

Options can be configured in the `licenseeForAndroid` extension:

```groovy
licenseeForAndroid {
enableKotlinCodeGeneration = false
generatedPackageName = "io.github.usefulness.licensee"
enableAndroidAssetGeneration = true
androidAssetFileName = "licensee_artifacts.json"
enableResourceGeneration = false
resourceFileName = "licensee_artifacts.json"
singularVariantName = null
}
```

- `enableKotlinCodeGeneration` - Generates a static list of open source assets
- `generatedPackageName` - Generate Kotlin code under given package
- `enableAndroidAssetGeneration` - Enable asset generation. Will copy licensee report to android asset directory making it available as `androidAssetFileName`
- `androidAssetFileName` - The name of the asset file the licensee report gets copied to.
- `singularVariantName` - The name of the build variant that all variants will use to have always the same licensed, regardless of app variant. (i.e. "productionRelease")
- `enableKotlinCodeGeneration` - Enables generating a static list of open source assets.
- `generatedPackageName` - Generate kotlin code under given package
- `enableResourceGeneration` - Enables copying _licensee_ report to asset(Android)/resource(JVM) directory, making it available under 'resourceFileName' name.
- `resourceFileName` - The name of the asset/resource file the licensee report gets copied to.
- `singularVariantName` - The name of the build variant that all variants will use to have always the same licensed, regardless of app variant. (i.e. `"paidRelease"`)

### Common recipes

#### Generate licensee information from any module

```groovy
plugins {
id("com.android.application") // or `com.android.library`
id("app.cash.licensee")
id("io.github.usefulness.licensee-for-android")
}
licensee {
allow("Apache-2.0")
}
licenseeForAndroid {
enableKotlinCodeGeneration = true
enableResourceGeneration = true
}
```
#### Generate Kotlin code in Kotlin-only module using licensee output from a different module

```groovy
plugins {
id("org.jetbrains.kotlin.jvm") // or any other module type
id("io.github.usefulness.licensee-for-android") apply(false) // do not generate licensee information for _this_ module
}
// Register custom, source-generating task, use `:app`'s `productionRelease` variant
def licenseeTarget = layout.buildDirectory.map { it.dir("generated/licensee") }
tasks.register("generateLicenseeKotlinCode", CodeGenerationTask) {
it.inputFile.set(
project(":app").tasks.named("licenseeAndroidProductionRelease")
.flatMap { it.outputDir.file("artifacts.json") }
)
it.outputDirectory.set(licenseeTarget)
it.packageName.set("io.github.usefulness.licensee")
}
// Make sources discoverable in IDE (https://youtrack.jetbrains.com/issue/KT-45161)
sourceSets.named("main") {
kotlin {
srcDir(licenseeTarget)
}
}
// Make them run on every compilation
tasks.named("compileKotlin") {
dependsOn("generateCustomLicenseeKotlinCode")
}
```

### Credits
Huge thanks to [premex-ab/gross](https://github.com/premex-ab/gross) which this plugin forked from.
Binary file added images/generated_code_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/generated_code_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions licensee-for-android/api/licensee-for-android.api
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
public abstract class io/github/usefulness/licensee/AssetCopyTask : org/gradle/api/DefaultTask {
public abstract class io/github/usefulness/licensee/CodeGenerationTask : org/gradle/api/DefaultTask {
public fun <init> ()V
public final fun action ()V
public abstract fun getInputFile ()Lorg/gradle/api/file/RegularFileProperty;
public abstract fun getOutputDirectory ()Lorg/gradle/api/file/DirectoryProperty;
public abstract fun getTargetFileName ()Lorg/gradle/api/provider/Property;
public abstract fun getPackageName ()Lorg/gradle/api/provider/Property;
}

public abstract class io/github/usefulness/licensee/CodeGenerationTask : org/gradle/api/DefaultTask {
public abstract class io/github/usefulness/licensee/LicenseeFileCopyTask : org/gradle/api/DefaultTask {
public fun <init> ()V
public final fun action ()V
public abstract fun getInputFile ()Lorg/gradle/api/file/RegularFileProperty;
public abstract fun getOutputDirectory ()Lorg/gradle/api/file/DirectoryProperty;
public abstract fun getPackageName ()Lorg/gradle/api/provider/Property;
public abstract fun getTargetFileName ()Lorg/gradle/api/provider/Property;
}

public class io/github/usefulness/licensee/LicenseeForAndroidExtension {
public fun <init> (Lorg/gradle/api/model/ObjectFactory;)V
public final fun getAndroidAssetFileName ()Lorg/gradle/api/provider/Property;
public final fun getEnableAndroidAssetGeneration ()Lorg/gradle/api/provider/Property;
public final fun getEnableKotlinCodeGeneration ()Lorg/gradle/api/provider/Property;
public final fun getEnableResourceGeneration ()Lorg/gradle/api/provider/Property;
public final fun getGeneratedPackageName ()Lorg/gradle/api/provider/Property;
public final fun getResourceFileName ()Lorg/gradle/api/provider/Property;
public final fun getSingularVariantName ()Lorg/gradle/api/provider/Property;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction

@CacheableTask
public abstract class AssetCopyTask : DefaultTask() {
public abstract class LicenseeFileCopyTask : DefaultTask() {
@get:OutputDirectory
public abstract val outputDirectory: DirectoryProperty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package io.github.usefulness.licensee
import org.gradle.api.Incubating
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.provider.SetProperty

public open class LicenseeForAndroidExtension(objectFactory: ObjectFactory) {

/**
* Generates a static list of open source assets
* Enables generating a static list of open source assets.
*/
public val enableKotlinCodeGeneration: Property<Boolean> = objectFactory.property(default = false)

Expand All @@ -18,15 +19,14 @@ public open class LicenseeForAndroidExtension(objectFactory: ObjectFactory) {
public val generatedPackageName: Property<String> = objectFactory.property(default = "io.github.usefulness.licensee")

/**
* Enable asset generation. Will copy licensee report to
* android asset directory making it available as 'androidAssetFileName'
* Enables copying licensee report to asset(Android)/resource(JVM) directory, making it available under 'resourceFileName' name.
*/
public val enableAndroidAssetGeneration: Property<Boolean> = objectFactory.property(default = true)
public val enableResourceGeneration: Property<Boolean> = objectFactory.property(default = false)

/**
* The name of the asset file the licensee report gets copied to.
* The name of the asset/resource file the licensee report gets copied to.
*/
public val androidAssetFileName: Property<String> = objectFactory.property(default = "licensee_artifacts.json")
public val resourceFileName: Property<String> = objectFactory.property(default = "licensee_artifacts.json")

/**
* The name of the build variant that all variants will use to have always the same licensed, regardless of app variant.
Expand All @@ -39,3 +39,7 @@ public open class LicenseeForAndroidExtension(objectFactory: ObjectFactory) {
internal inline fun <reified T> ObjectFactory.property(default: T? = null): Property<T> = property(T::class.java).apply {
convention(default)
}

internal inline fun <reified T> ObjectFactory.setProperty(default: Set<T>? = null): SetProperty<T> = setProperty(T::class.java).apply {
convention(default)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.android.build.api.variant.AndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.reporting.ReportingExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetContainer

public class LicenseeForAndroidPlugin : Plugin<Project> {

Expand All @@ -21,6 +22,13 @@ public class LicenseeForAndroidPlugin : Plugin<Project> {
configureAndroidPlugin(extension)
}
}

listOf("org.jetbrains.kotlin.jvm")
.forEach { pluginId ->
pluginManager.withPlugin(pluginId) {
project.afterEvaluate { configureKotlinPlugin(extension) }
}
}
}
}

Expand All @@ -37,18 +45,21 @@ public class LicenseeForAndroidPlugin : Plugin<Project> {
val licenseeTaskName = "licenseeAndroid$sourceCapitalized"

val artifactsFile = reportingExtension.file("licensee/android$sourceCapitalized/artifacts.json")
if (extension.enableAndroidAssetGeneration.get()) {

if (extension.enableResourceGeneration.get()) {
val copyArtifactsTask = tasks.register(
"generate${sourceCapitalized}LicenseeAssetsFor$targetCapitalized",
AssetCopyTask::class.java,
"generate${sourceCapitalized}LicenseeResourceFor$targetCapitalized",
LicenseeFileCopyTask::class.java,
) {
it.inputFile.set(artifactsFile)
it.targetFileName.set(extension.androidAssetFileName)
it.targetFileName.set(extension.resourceFileName)
}

variant.sources.assets!!.addGeneratedSourceDirectory(
taskProvider = copyArtifactsTask,
wiredWith = AssetCopyTask::outputDirectory,
wiredWith = LicenseeFileCopyTask::outputDirectory,
)

copyArtifactsTask.configure { it.dependsOn(licenseeTaskName) }
}

Expand All @@ -71,4 +82,48 @@ public class LicenseeForAndroidPlugin : Plugin<Project> {
}
}
}

private fun Project.configureKotlinPlugin(extension: LicenseeForAndroidExtension) {
val reportingExtension = extensions.getByType(ReportingExtension::class.java)
val kotlinExtension = project.extensions.getByType(KotlinSourceSetContainer::class.java)
val licenseeTaskName = "licensee"

val artifactsFile = reportingExtension.file("licensee/artifacts.json")
if (extension.enableResourceGeneration.get()) {
val kotlinSourceSet = kotlinExtension.sourceSets.named("main").get().resources
val targetDirectory = layout.buildDirectory.map { it.dir("generated").dir("licenseeResources") }

val copyArtifactsTask = tasks.register("generateLicenseeResource", LicenseeFileCopyTask::class.java) {
it.inputFile.set(artifactsFile)
it.targetFileName.set(extension.resourceFileName)
it.outputDirectory.set(targetDirectory)
}
kotlinSourceSet.srcDir(targetDirectory)

copyArtifactsTask.configure { it.dependsOn(licenseeTaskName) }

tasks.named("processResources") {
it.dependsOn(copyArtifactsTask)
}
}

if (extension.enableKotlinCodeGeneration.get()) {
val targetDirectory = layout.buildDirectory.map { it.dir("generated").dir("licensee") }
val codeGenerationTask = tasks.register("generateLicenseeKotlinCode", CodeGenerationTask::class.java) {
it.inputFile.set(artifactsFile)
it.packageName.set(extension.generatedPackageName)
it.outputDirectory.set(targetDirectory)
}

kotlinExtension.sourceSets.named("main") {
it.kotlin.srcDir(targetDirectory)
}

tasks.named("compileKotlin") {
it.dependsOn(codeGenerationTask)
}

codeGenerationTask.configure { it.dependsOn(licenseeTaskName) }
}
}
}
12 changes: 6 additions & 6 deletions sample/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ licensee {

licenseeForAndroid {
enableKotlinCodeGeneration = true
enableAndroidAssetGeneration = true
enableResourceGeneration = true
}
android {
namespace "io.githhub.usefulness.licensee.android.app"
Expand All @@ -28,15 +28,15 @@ android {
matchingFallbacks += ["debug"]
}
}
lint {
checkReleaseBuilds = false
buildFeatures {
compose = true
buildConfig = true
}
testOptions {
unitTests.includeAndroidResources true
}
buildFeatures {
compose = true
buildConfig = true
lint {
checkReleaseBuilds = false
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
Expand Down
18 changes: 9 additions & 9 deletions sample/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Gross"
tools:targetApi="31">
tools:targetApi="31"
>
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Gross">
android:theme="@style/Theme.Gross"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand All @@ -25,4 +25,4 @@
</activity>
</application>

</manifest>
</manifest>
Loading

0 comments on commit f11daa7

Please sign in to comment.