Gradle, cmake and assets

Hello everyone!

I have a gradle dsl project that uses cmake to build native libraries. At the very end of the cmakelists.txt it copies all asset files to the actual asset folder (app/src/main/assets) but these never get included in the apk unless I run gradle a second time. I’m guessing that’s from the assets already being in place.

Is there any way to have gradle add the new assets to the build?

For context this is what I’m actually doing

https://gitlab.com/duron27/alpha3/-/blob/main/app/src/main/cpp/openmw/CMakeLists.txt?ref_type=heads#L764

At the very end of the cmakelists.txt it copies all asset files to the actual asset folder (app/src/main/assets)

That sounds like a very bad idea.
No idea how your build is structured, but I guess you have some task that calls this cmake build and produces the intended output files.
This task should - like all tasks - have its inputs and outputs declared properly, so that it can be up-to-date or cached.
This task (yes, the task itself or a provider for it) is then registered as source dir for the respective source directory set.

As it is an Android build, it could of course also be somehow different, as Android builds are always a bit special. I don’t do Android, so I don’t know for sure, but also the usual Android build should have some way to properly register task-generated files.
Copying things to a source folder should never be an appropriate way.

placing this

androidComponents {
    onVariants { variant ->
        val cap = variant.name.replaceFirstChar { it.uppercase() }
        tasks.withType<MergeSourceSetFolders>().configureEach {
            if (name == "merge${cap}Assets") {
                dependsOn("buildCMake${cap}")
                dependsOn("configureCMake${cap}")
                outputs.upToDateWhen { false }
            }
        }
    }
}

in my build.gradle.kts solved the issue for me
this is the spot and also my repo

No, that does not “solve” anything, it at most is a very flaky work-around.

Practically any manual dependsOn where not a lifecycle task is on the left-hand side is a code-smell and usually - as in your case - a sign that task outputs are not properly wired to task inputs which would bring in necessary task dependencies implicitly.

For example any other task that needs assets like maybe a source jar task or some analysis task and so on will also all miss the task dependency and work on missing or stale files eventually.

Also outputs.upToDateWhen { false } should never be done today.
If you want the task to not be up-to-date, use doNotTrackState().
But always better is to fix the inputs and outputs of the task, unless the task outcome depends on some external state like the contents of a database or the result of some web call or similar.

I don’t really know how to do this, I’ll read up on it I guess. In my opinion if you are building any native code in your app with gradlew it should then just check the assets folder to see if it’s been changed since it last checked. This is an extremely common thing for anyone porting open source game engines to android and not wanting to use bash scripts.

it should then just check the assets folder to see if it’s been changed since it last checked

Sure, it does.
That’s not the point.
If you miss the task dependency, you use absent or stale files as the task that produces the files was not run first.
These dependencies can be declared manually like you did, you just should not do it, as you can easily miss further needed dependencies, can miss to remove them if no longer needed, and so on, and it is discouraged bad practice to do so.

I’ll I’m on phone at work but I updated the code to register the build process as a task, then have assets depend on that task. If that’s preferable

I did not really get that.
It was already a task, wasn’t it?

Not exactly, even though it’s working fine in sure it’s still wrong. I’m not finding any info on a list of available tasks that you should register to do what I’m doing. In fact it’s hard to find any info at all that is consistent and not what I’m already doing.

Do you have any links that clearly outlines what I should be doing?

As I said, I don’t do Android, so no I don’t have any links how to do it with AGP.