kotlin icon indicating copy to clipboard operation
kotlin copied to clipboard

add resources to klib

Open jiqimaogou opened this issue 4 years ago • 19 comments

problem

If we publish a Kotlin Native library. It will take the klib file outputed by compileKotlinNative task.

the klib file's layout like this:

image

It has a resources directory which is empty, even I put some file in common resources directory.

image

reason

the ${target}ProcessResources task will merge common resources directory and target resources directory into build/processedResources/native/main directory.

image

And Kotlin gradle plugin create a ${target}Jar task for some target, like js and jvm target. for example:

  1. js target's jar task is jsJar.
  2. jvm target's jar task is jvmJar.

and ${target}Jar task will archive:

  1. Kotlin compile output directory
  2. Kotlin resources directory

so ${target}Jar task depends on these two output. for example:

  1. jsJar depends on:

    1. compileKotlinJs
    2. jsMainClasses which depends on jsProcessResources
  2. jvmJar depends on:

    1. compileKotlinJvm
    2. jvmMainClasses which depends on jvmProcessResources

compileKotlinJvm and jvmMainClasses are two separate task. they don't depends on each other.

js target or jvm target will publish the jar outputed by ${target}Jar task.

Kotlin Native problem

Kotlin Native publishes the klib file outputed by compileKotlinNative task, which does not depend on nativeProcessResources task, and compileKotlinNative task has not resources input property.

the solution

  1. make compileKotlinNative task depends on nativeProcessResources task.
  2. pass the resources directory to compileKotlinNative task, and copy the resources directory to klib resources directory.

result

image

TODO

when create a binary contains resources(like iOS framework), merge all dependencies klib resources directory into framework.

jiqimaogou avatar Apr 30 '21 08:04 jiqimaogou

@abelkov hello, can you add a reviewer for my push?

jiqimaogou avatar May 10 '21 23:05 jiqimaogou

Hey, thanks a lot for the contribution!

We need to discuss it with the team. Unfortunately, some relevant folks are absent on this week. I'll follow-up somewhere around the next week (17th of May -- 21st of May)

dsavvinov avatar May 11 '21 13:05 dsavvinov

Hey, thanks a lot for the contribution!

We need to discuss it with the team. Unfortunately, some relevant folks are absent on this week. I'll follow-up somewhere around the next week (17th of May -- 21st of May)

ok, thanks. Kotlin JS has the sample problem. I have mentioned in https://github.com/JetBrains/kotlin/pull/4385.

jiqimaogou avatar May 11 '21 15:05 jiqimaogou

Hey, thanks a lot for the contribution!

We need to discuss it with the team. Unfortunately, some relevant folks are absent on this week. I'll follow-up somewhere around the next week (17th of May -- 21st of May)

hello, what's the progress of this issue.

jiqimaogou avatar May 24 '21 07:05 jiqimaogou

We need some more time to discuss it, sorry.

To give you some context: the design of resources in MPP and in klibs in particular is still work-in-progress. Therefore, we need to make sure that the proposed changes align nicely at least with possible future work in that area, least we'll have to deprecate and phase out those changes in like half a year. We're evaluating other possible options and workarounds, as well as the amount of pain they will cause compared to out-of-the-box solution vs. the probability of those solutions to need deprecation in future.

dsavvinov avatar May 24 '21 11:05 dsavvinov

@jiqimaogou could you please describe a bit your use case of resources in klib? The PR adds some logic to put resources into zipped klib without using them. Seems like at least that kind of work could be done on the build script level (produce unzipped klib, copy resource folder into compiler output dir, zip it using corresponding zip task).

romanart avatar May 24 '21 14:05 romanart

@jiqimaogou could you please describe a bit your use case of resources in klib? The PR adds some logic to put resources into zipped klib without using them. Seems like at least that kind of work could be done on the build script level (produce unzipped klib, copy resource folder into compiler output dir, zip it using corresponding zip task).

In the TODO, I will put klib resources into iOS framework. I will do it this week. the use case is that I make a home module as a klib, and I will put some resources(like international strings) into klib, and read it in platform native code.

in Android, AAR contains code and resources. in iOS, the framework contains code and resources. in Java, the jar contains code and resources.

I think as a Kotlin module, it may be reasonable to contain resources.

jiqimaogou avatar May 25 '21 02:05 jiqimaogou

@jiqimaogou Thank you for your response.

and read it in platform native code.

Why do you think those resources going to be accessible in your application? There is some extra that has to be done either on the compiler side or build side to make that possible. I would prefer the build side TBH.

I think as a Kotlin module, it may be reasonable to contain resources.

I agree with that.

romanart avatar May 25 '21 09:05 romanart

@jiqimaogou Thank you for your response.

and read it in platform native code.

Why do you think those resources going to be accessible in your application? There is some extra that has to be done either on the compiler side or build side to make that possible. I would prefer the build side TBH.

I think as a Kotlin module, it may be reasonable to contain resources.

I agree with that.

yes, we can do it on the build side. I put it on the compiler side, because compile and Link are the same task with different compile options. If I do it on the build side, I must create a new task depends on the Link framework, and merge resources with the framework in the new place. If I put it on the compiler side, it will be less complicated.

I want to know is, does the Kotlin team has a plan to support contains resources in the Kotlin module? If you have a plan, I think the official team's implementation is more suitable. My push request purpose is just to take my push request as a reference. It may be more convincing to write code than submit an issue.

jiqimaogou avatar May 25 '21 12:05 jiqimaogou

I want to know is, does the Kotlin team has a plan to support contains resources in the Kotlin module?

Yes, we have such plan.

Anyway, it would be great if you create an issue in YT with a short description of your use-case, even with reference to this PR.

Do you need any help with build script code?

romanart avatar May 25 '21 18:05 romanart

I want to know is, does the Kotlin team has a plan to support contains resources in the Kotlin module?

Yes, we have such plan.

Anyway, it would be great if you create an issue in YT with a short description of your use-case, even with reference to this PR.

Do you need any help with build script code?

I have create a issue: https://youtrack.jetbrains.com/issues?q=project:%20%7BKT%7D&preview=KT-46956

jiqimaogou avatar May 26 '21 05:05 jiqimaogou

@jiqimaogou Thank you for issue.

So do you need any help with build script?

romanart avatar May 26 '21 09:05 romanart

@jiqimaogou Thank you for issue.

So do you need any help with build script?

sorry, I don't know the context of the build script. Is it the feature of packaging the klib resources into the framework I will do later?

I don't know if I must continue, I don't know the Kotlin team's plan, maybe you have a different implementation?

jiqimaogou avatar May 26 '21 12:05 jiqimaogou

@jiqimaogou Thank you for issue. So do you need any help with build script?

sorry, I don't know the context of the build script. Is it the feature of packaging the klib resources into the framework I will do later?

I don't know if I must continue, I don't know the Kotlin team's plan, maybe you have a different implementation?

I mean do you need any help with how to put resources into klib using gradle?

I don't know the Kotlin team's plan, maybe you have a different implementation?

We don't actually. The implementation should naturally come from design which is led by use cases. So now we have the first use case. I believe your implementation is completely correct but to be accepted first requires some extra work from Kotlin team.

romanart avatar May 26 '21 15:05 romanart

@jiqimaogou Thank you for issue. So do you need any help with build script?

sorry, I don't know the context of the build script. Is it the feature of packaging the klib resources into the framework I will do later? I don't know if I must continue, I don't know the Kotlin team's plan, maybe you have a different implementation?

I mean do you need any help with how to put resources into klib using gradle?

I don't know the Kotlin team's plan, maybe you have a different implementation?

We don't actually. The implementation should naturally come from design which is led by use cases. So now we have the first use case. I believe your implementation is completely correct but to be accepted first requires some extra work from Kotlin team.

yes, I need some help.

val shouldAddCompileOutputsToElements = compilation.owner is KotlinGradleVariant || compilation.isMainCompilationData()

when compilation.owner is KotlinGradleVariant is true and compilation.isMainCompilationData() is false?

I found it may publish multiple klib files at once.

jiqimaogou avatar May 27 '21 11:05 jiqimaogou

when compilation.owner is KotlinGradleVariant is true and compilation.isMainCompilationData() is false?

For now, compilation.owner is KotlinGradleVariant is true only in our experimental (not officially released) plugins. In those plugins, not just the main parts of a project might be exposed to project-to-project dependencies, but other parts as well. If you only aim to work with the org.jetbrains.kotlin.multiplatform plugin, you can safely assume that compilation.owner is KotlinGradleVariant is always false.

h0tk3y avatar May 28 '21 08:05 h0tk3y

@romanart I have updated my commit, put the resources file into klib with at build script side instead of compiler side.

the solution

In Java, it creates a task named ${target}Jar packages main(only) compilation outputs.

image

In my solution for Kotlin native:

image

I create a task named ${compilation}Klib(maybe the task name is not well) packages every compilation output and publishes the output.

if the commit is OK, I will do the next step to package all klib resources into the ios framework.

jiqimaogou avatar May 31 '21 07:05 jiqimaogou

@jiqimaogou Thanks! It's good to have your PR as a reference for a future implementation once we have a proper design for resources in Kotlin/Native KLIBs and binaries!

As you can see, our current implementation of KLIB generation is somewhat inconsistent in that some tasks (for platform-specific compilations) pack a KLIB directly as an archive, and some tasks (those for common/intermediate source sets) produce an unpacked KLIB. So if you want to package resources into the outputs without the changes in this PR, using just the build script, probably the easiest way would be to add some code to the tasks using doLast and write the resources to the output directory or the KLIB, depending on what the task produces.

h0tk3y avatar May 31 '21 08:05 h0tk3y

@jiqimaogou Thanks! It's good to have your PR as a reference for a future implementation once we have a proper design for resources in Kotlin/Native KLIBs and binaries!

As you can see, our current implementation of KLIB generation is somewhat inconsistent in that some tasks (for platform-specific compilations) pack a KLIB directly as an archive, and some tasks (those for common/intermediate source sets) produce an unpacked KLIB. So if you want to package resources into the outputs without the changes in this PR, using just the build script, probably the easiest way would be to add some code to the tasks using doLast and write the resources to the output directory or the KLIB, depending on what the task produces.

OK, I know, the Kotlin team has not the proper design yet. So at current, it's recommended to implement the feature in my own build.gradle file instead of in the Kotlin repository.

jiqimaogou avatar May 31 '21 08:05 jiqimaogou