Skip to content

Comments

Update project build configuration and dependencies#514

Merged
programadorthi merged 31 commits intoadrielcafe:mainfrom
dzmpr:dependencies_update
Aug 17, 2025
Merged

Update project build configuration and dependencies#514
programadorthi merged 31 commits intoadrielcafe:mainfrom
dzmpr:dependencies_update

Conversation

@dzmpr
Copy link
Contributor

@dzmpr dzmpr commented Dec 1, 2024

Hi there!
I have some troubles with m2 bottom sheet navigator so I decided to add m3 bottom sheet navigator and solve this problem for me and for others. But when I started working on it I saw that voyager uses compose multiplatform 1.6.11 when I needed 1.7. One after another I'm ended up made some improvement to project build configuration and updated all dependencies (not only compose kmp).
So, what's have been done:

  • Updated gradle and dependencies.
  • Cleaned up project from redundant .gitignore and customer.proguard.pro files.
  • Got rid of buildSrc and replace it with build-config included build. With buildSrc there are problems with using version catalogs and no pros.
  • Split modules configuration to pluggable convention plugins to make configuration simpler and cleaner.
  • Removed some unused or redundant dependencies (such as appcompat, compose-runtimeSaveable, compose-compiler, compose-animations, and maybe something else). Note: this compose dependencies are not multiplatform and only used in samples.
  • Replaced com.benasher44:uuid dependency with kotlin stdlib implementation which is available from kotlin 2.0.
  • Replaced compileOnly for compose dependencies with plain implementation as now seems all working fine but with compileOnly compiler threw warnings about js targets.
  • Fixed js sample and some more minor fixes for samples.

What's I left behind:

  • I can't figure out custom target hierarchy that voyager uses, so left it as is (with jvm("desktop") target which triggers compiler warning).
  • Didn't update api dump, because I removed ExperimentalVoyagerApi from nonPublicMarkers (I consider this is a mistake, because it' actually public api, just experimental). So if you are okay with this I update api with additional commit.

I've tested all samples on android and following targets of multiplatform sample: js, wasm, macos (not sure what target).

So I'm waiting for review, and open for any questions if you have one.

mavenPublish = "0.30.0"
composeMultiplatform = "1.7.1"
binaryCompatibilityValidator = "0.16.3"
atomicfu = "0.26.1"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi, this will currently cause an issue because compose expects (and forces) 0.23.2.
Seems to be a known issue https://youtrack.jetbrains.com/issue/CMP-5831

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's compose multiplatform problem rather than voyager. Anyway I tested voyager with cmp 1.8.0-rc01 and it seems all works fine.
I intended to update this PR when cmp 1.8.0 will be released.

@hafiz013
Copy link

@Vodes why did you change from 8.2 => 8.11.1 It is to new mine one still using 8.7.2

@Syer10
Copy link
Contributor

Syer10 commented Feb 17, 2025

@Vodes why did you change from 8.2 => 8.11.1 It is to new mine one still using 8.7.2

Because its good practice to always update dependencies, Gradle is always meant to be up-to-date for the improvements in speed and bugfixes.

@hafiz013
Copy link

@Syer10 has this fork or pr merge to master repo veyoger?

@dzmpr
Copy link
Contributor Author

dzmpr commented May 20, 2025

Just updated this PR, what did I done more:

  • Renamed jvm targets group to commonJvm to make it non-ambigious with jvm target.
  • Disabled android resources in library modules as voyager doesn't use them. It should have positive impact on build speed.
  • Removed package from AndroidManifest's as from AGP 8.0 namespace should be declared in module build.gradle file.
  • Updated CMP to 1.8.0, Kotlin to 2.1.21, Gradle to 8.14, and other dependencies to the most actual versions. The only exception is koin as they mistakenly removed required targets from latest releases. So I'm waiting for this issue to be done to update koin.

There is still some work to be done, e.g. update ktlint and resolve problems that it finds and update samples. But this is out of scope of this PR, so I intended to do this after this PR is merged.

@devnatan, @DevSrSouza can you please take a look at this PR.

Copy link
Collaborator

@programadorthi programadorthi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share evidences of all samples working after the whole changes?


# IntelliJ
*.iml
*.focus No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.focus files are generated by dropbox plugin.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the dropbox plugin, voyager project is a small project for using the plugin honestly.


if (isAndroidLibraryModule()) {
val proguardFilename = "consumer-rules.pro"
if (layout.projectDirectory.file(proguardFilename).asFile.exists()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need check if exists. AGP ignores the file whether it doesn't exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGP will print that certain proguard files not found:

Supplied consumer proguard configuration does not exist: /Users/dzmitry/AndroidStudioProjects/voyager/voyager-bottom-sheet-navigator/consumer-rules.pro

If you ok with this I remove an if clause.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed the empty files. That is the reason to complain about missing it.
Is there any advantage to remove the files instead of putting the check for them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion a project has less clutter when it doesn't have files that don't affect anything.

}
}

androidTarget {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it makes sense having androidTarget in a file that have desktop configuration?

plugins.apply("org.jlleitschuh.gradle.ktlint")

configure<KtlintExtension> {
version.set("0.47.1")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you get the value from version catalog?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I can with hack like this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this?

add(projects.samples.multiModule.navigation)
}
with(nonPublicMarkers) {
add("cafe.adriel.voyager.core.annotation.InternalVoyagerApi")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why removed ExperimentalVoyagerApi?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually code marked with ExperimentalVoyagerApi is a part of public API surface of the voyager. So it shouldn't be treated as non-public and developer need to be aware about changes in this code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string is with spaces, does this is correct? Second is that ExperimentalVoyagerApi is meant to be not in the API Surface because it should be a API that can be change at any time, the project Binary Compatibility should try to always be incremental and not change existing APIs, this is why the annotation is not there in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your reasoning but API marked with this annotation is still public. I think developer should be aware when doing changes even to this code as consumers still can depend on it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Samples is not a good name to this catalog because it'll conflicts with the samples folder and creating confusion from we're getting the dependencies. Keeping all versioning in an unique file isn't a problem.

Copy link
Contributor Author

@dzmpr dzmpr May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain what conflicts do you mean? Samples modules are accessed through projects.samples.* while dependencies just with samples.*.
Maybe libsSamples.* or samplesLibs.* or demo.* will be a better naming?

I think it's good to have more fine-grained control over what dependencies you add to the library. Now it's not possible to 'accidentally' add new dependency from common catalog. With separate catalogs you need to make a mindful decision to add it to to libs catalog and it's becomes more clear to the reviewer when new dependency were added to library.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe samplesCatalog? I'm not good with names. For the first read I made assumptions between projects.samples and samples.*. Then a I realized that was a catalog.

android:name=".App"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:theme="@android:style/Theme.Material.Light.NoActionBar"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well you can change directly to androidx.material theme.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a compose app which uses compose theme instead of xml one. So I removed appcompat dependency and used built-in theme.

Comment on lines 30 to 31
gradlePluginPortal()
mavenLocal()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two guys will increase the resolution. Why they are here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'll remove them

jvmTest.dependencies {
implementation(libs.junit.api)
runtimeOnly(libs.junit.engine)
implementation(compose.runtime)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Voyager uses compileOnly to avoid transitive dependency at compile time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems using compileOnly for compose dependencies break compilation for certain targets, here the warning I get:

A compileOnly dependency is used in targets: Kotlin/JS, Kotlin/Native, Kotlin/Wasm.
Dependencies:
    - org.jetbrains.compose.runtime:runtime-saveable:1.8.1 (source sets: iosArm64Main, iosSimulatorArm64Main, iosX64Main, jsMain, macosArm64Main, macosX64Main, wasmJsMain)
    - org.jetbrains.compose.runtime:runtime:1.8.1 (source sets: iosArm64Main, iosSimulatorArm64Main, iosX64Main, jsMain, macosArm64Main, macosX64Main, wasmJsMain)

Using compileOnly dependencies in these targets is not currently supported, because compileOnly dependencies must be present during the compilation of projects that depend on this project.

To ensure consistent compilation behaviour, compileOnly dependencies should be exposed as api dependencies.

Furthermore, it is not possible to use voyager without using compose, why we should to avoid making a transitive dependency here? We not strictly enforce compose version so consumer just will use more recent version of compose.

I also checked out decompose for reference and it using implementation without any problems as it seems.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why this is showing is because of the change in the gradle.properties. There is a flag that the project had enable.

Can you hole back this? for now? This is a relative big change that I need to check with some Kotlin folks to see if the relocation of Compose KMP and Android libraries of Compose does not have the past issues anymore.

private fun getHooks(): List<ProvidedValue<*>> {
atomicAppContext.compareAndSet(null, LocalContext.current.applicationContext)
atomicParentLifecycleOwner.compareAndSet(null, LocalLifecycleOwner.current)
atomicParentLifecycleOwner.compareAndSet(null, LocalLifecycleOwner.current) // deprecated
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the comment

@hafizkloudius014
Copy link

When can this will merge to master?

@programadorthi
Copy link
Collaborator

I think soon it'll be merged. It's a good contribution. Just some adjustments and done.

@hafizkloudius014
Copy link

hafizkloudius014 commented May 22, 2025

@dzmpr i found bugs regarding to parseable serialize.

error : when time you off the screen and come back to screen error about parse. so i come out this solution but don't know how to constribute:

abstract class BasedActivityScreen : Screen, JavaSerializable{   //<-- without JavaSerializable will be error.
    @Composable
    override fun Content() {
        previewScreen()
    }

    @Preview
    @Composable
    open fun previewScreen(){}
}

and i hope that

public expect interface Screen { <-- can add parceable

    public open val key: ScreenKey

    @Composable
    public fun Content()
}

internal fun Screen.commonKeyGeneration() =
    this::class.multiplatformName ?: error("Default ScreenKey not found, please provide your own key")

@programadorthi
Copy link
Collaborator

@hafizkloudius014 Screen is JavaSerializable by default. More details here.

@hafizkloudius014
Copy link

Is this pr good to go to merge?

Comment on lines +14 to +22
eachPlugin {
if (requested.version == null) return@eachPlugin
when (requested.id.id) {
"com.android.tools.build" -> {
useModule("${requested.id.id}:gradle:${requested.version}")
}
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default Gradle to resolve plugin artifact by plugin id uses plugin id as group id and add .gradle.plugin suffix to plugin id to construct artifact id. So plugin "pluginId" version "1.0.0" becomes "pluginId:pluginId.gradle.plugin:1.0.0" artifact.
But AGP build plugin has custom artifact id which we need to override.

@DevSrSouza
Copy link
Collaborator

DevSrSouza commented Jun 2, 2025

Can you revert back to use compileOnly in dependencies? and add the following flag to the gradle.properties should skip the warning you are seeing.

# Compose dependencies currently requires to be CompileOny if we want to both
# support Android only projects and multiplatform projects.
# based on the issue below, it seems to only have issues with compileOnly
# when cache is enable, so, based on the currently state of Compose Multiplatform
# the native target also does not work propertly with caching, so, any compose project
# will require `kotlin.native.cacheKind=none` making possible to we continue using compileOnly.
# https://youtrack.jetbrains.com/issue/KT-46377
kotlin.native.ignoreIncorrectDependencies=true

edit:
I will try to run this PR locally and I will check if publishing locally with implementation and consuming in a pure Android compose project to see if there will be any issues (in the past it had), if I don't find any, we can keep the implementation() usage.

@dzmpr
Copy link
Contributor Author

dzmpr commented Jun 14, 2025

I think now we ready to merge and release new version

@dzmpr
Copy link
Contributor Author

dzmpr commented Jun 20, 2025

@DevSrSouza Hey, did you get a chance to test the PR locally with implementation as you mentioned?

@dzmpr
Copy link
Contributor Author

dzmpr commented Jul 2, 2025

Since July of 2025 OSS sonatype repository is out of service so all new publications should go through cetral portal. I updated publishing configuration, now we need to migrate voyager namespace to center portal (here short instruction and here is official one) and update project secrets (SONATYPE_NEXUS_USERNAME and SONATYPE_NEXUS_PASSWORD) with newly generated ones.
@DevSrSouza @programadorthi

@hafiz013
Copy link

hafiz013 commented Jul 2, 2025

hi it is already july, it is ok can merge this pr? thanks you.

Copy link
Collaborator

@devnatan devnatan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hafiz013
Copy link

hafiz013 commented Jul 4, 2025

nice it approved. may i know what is latest version of this library? thank you

@zouyonghao
Copy link

Any updates?

@hafizkloudius014
Copy link

hi @programadorthi and @DevSrSouza when can get the approval?

@Robotxm
Copy link

Robotxm commented Jul 22, 2025

Any updates on this PR?

@dzmpr
Copy link
Contributor Author

dzmpr commented Aug 5, 2025

@DevSrSouza Hi, can you please take a look at this PR? There is one step left to release and unblock other improvements for the lib.

@programadorthi programadorthi merged commit 670dddc into adrielcafe:main Aug 17, 2025
1 check passed
@hafizkloudius014
Copy link

hi @programadorthi should be increase the number of version library before can merge to main?

@Robotxm
Copy link

Robotxm commented Aug 26, 2025

Hi @programadorthi, it seems that publish of new version is failed. Will it be fixed?

@hafizkloudius014
Copy link

hi @programadorthi error:

Failed to stop service 'sonatype-repository-build-service'.
> Upload failed: {"error":{"message":"Invalid token"}}

@dzmpr
Copy link
Contributor Author

dzmpr commented Sep 2, 2025

I think this #514 (comment) may be a problem.

@hafizkloudius014
Copy link

ok then their problem not migrate the portal. @dzmpr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants