[cmake, frontend] Add nightly build modifier (#3431)

The `NIGHTLY_BUILD` option changes the app name to "Eden Nightly" and
changes the auto-update URL to use our new Nightly repository.

This needs added to Android, but I can't right now as I have to leave.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3431
This commit is contained in:
crueter 2026-01-31 01:18:36 +01:00
parent df838a57fd
commit 638663b28e
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
12 changed files with 160 additions and 50 deletions

View file

@ -5,6 +5,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// import android.annotation.SuppressLint
import com.android.build.gradle.api.ApplicationVariant
import kotlin.collections.setOf
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
@ -37,6 +38,9 @@ android {
compileSdkVersion = "android-36"
ndkVersion = "28.2.13676358"
val isNightly =
providers.gradleProperty("nightly").orNull?.toBooleanStrictOrNull() ?: false
buildFeatures {
viewBinding = true
}
@ -71,6 +75,7 @@ android {
val extraCMakeArgs =
(project.findProperty("YUZU_ANDROID_ARGS") as String?)?.split("\\s+".toRegex())
?: emptyList()
arguments.addAll(
listOf(
"-DENABLE_QT=0", // Don't use QT
@ -89,6 +94,13 @@ android {
)
)
if (isNightly) {
arguments.addAll(listOf(
"-DENABLE_UPDATE_CHECKER=ON",
"-DNIGHTLY_BUILD=ON",
))
}
abiFilters("arm64-v8a")
}
}
@ -125,7 +137,12 @@ android {
signingConfigs.getByName("default")
}
manifestPlaceholders += mapOf("appNameSuffix" to "")
if (isNightly) {
applicationIdSuffix = ".nightly"
manifestPlaceholders += mapOf("appNameSuffix" to " Nightly")
} else {
manifestPlaceholders += mapOf("appNameSuffix" to "")
}
isMinifyEnabled = true
isDebuggable = false
@ -239,6 +256,15 @@ android {
path = file("${edenDir}/CMakeLists.txt")
}
}
productFlavors.all {
val currentName = manifestPlaceholders["appNameBase"] as? String ?: "Eden"
val suffix = if (isNightly) " Nightly" else ""
// apply nightly suffix I/A
resValue("string", "app_name_suffixed", "$currentName$suffix")
resValue("string", "app_name", "Eden$suffix")
}
}
idea {
@ -258,7 +284,7 @@ tasks.register<Delete>("ktlintReset", fun Delete.() {
val showFormatHelp = {
logger.lifecycle(
"If this check fails, please try running \"gradlew ktlintFormat\" for automatic " +
"codestyle fixes"
"codestyle fixes"
)
}
tasks.getByPath("ktlintKotlinScriptCheck").doFirst { showFormatHelp.invoke() }

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
@ -218,7 +218,7 @@ object NativeLibrary {
/**
* Checks for available updates.
*/
external fun checkForUpdate(): String?
external fun checkForUpdate(): Array<String>?
/**
* Return the URL to the release page
@ -228,13 +228,18 @@ object NativeLibrary {
/**
* Return the URL to download the APK for the given version
*/
external fun getUpdateApkUrl(version: String, packageId: String): String
external fun getUpdateApkUrl(tag: String, artifact: String, packageId: String): String
/**
* Returns whether the update checker is enabled through CMAKE options.
*/
external fun isUpdateCheckerEnabled(): Boolean
/**
* Returns whether or not this is a nightly build.
*/
external fun isNightlyBuild(): Boolean
/**
* Returns the build version generated by CMake (BUILD_VERSION).
*/

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.ui.main
@ -183,18 +183,26 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
val latestVersion = NativeLibrary.checkForUpdate()
if (latestVersion != null) {
runOnUiThread {
showUpdateDialog(latestVersion)
val tag: String = latestVersion[0]
val name: String = latestVersion[1]
showUpdateDialog(tag, name)
}
}
}.start()
}
private fun showUpdateDialog(version: String) {
private fun showUpdateDialog(tag: String, name: String) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.update_available)
.setMessage(getString(R.string.update_available_description, version))
.setMessage(getString(R.string.update_available_description, name))
.setPositiveButton(android.R.string.ok) { _, _ ->
downloadAndInstallUpdate(version)
var artifact = tag
// Nightly builds have a slightly different format
if (NativeLibrary.isNightlyBuild()) {
val splitTag = tag.split('.')
artifact = splitTag.subList(1, splitTag.size - 1).joinToString(".")
}
downloadAndInstallUpdate(tag, artifact)
}
.setNeutralButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
@ -207,11 +215,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
.show()
}
private fun downloadAndInstallUpdate(version: String) {
private fun downloadAndInstallUpdate(version: String, artifact: String) {
CoroutineScope(Dispatchers.IO).launch {
val packageId = applicationContext.packageName
val apkUrl = NativeLibrary.getUpdateApkUrl(version, packageId)
val apkFile = File(cacheDir, "update-$version.apk")
val apkUrl = NativeLibrary.getUpdateApkUrl(version, artifact, packageId)
val apkFile = File(cacheDir, "update-$artifact.apk")
withContext(Dispatchers.Main) {
showDownloadProgressDialog()

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
@ -1595,7 +1595,6 @@ JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_updatePowerState(
g_has_battery.store(hasBattery, std::memory_order_relaxed);
}
// return #ifdef ENABLE_UPDATE_CHECKER
JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_isUpdateCheckerEnabled(
JNIEnv* env,
jobject obj) {
@ -1606,22 +1605,47 @@ JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_isUpdateChecker
#endif
}
JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_isNightlyBuild(
JNIEnv* env,
jobject obj) {
#ifdef NIGHTLY_BUILD
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
#ifdef ENABLE_UPDATE_CHECKER
JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_checkForUpdate(
JNIEXPORT jobjectArray JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_checkForUpdate(
JNIEnv* env,
jobject obj) {
const bool is_prerelease = ((strstr(Common::g_build_version, "pre-alpha") != nullptr) ||
(strstr(Common::g_build_version, "alpha") != nullptr) ||
(strstr(Common::g_build_version, "beta") != nullptr) ||
(strstr(Common::g_build_version, "rc") != nullptr));
const std::optional<std::string> latest_release_tag =
const std::optional<UpdateChecker::Update> release =
UpdateChecker::GetLatestRelease(is_prerelease);
if (latest_release_tag && latest_release_tag.value() != Common::g_build_version) {
return env->NewStringUTF(latest_release_tag.value().c_str());
if (!release || release->tag == Common::g_build_version) {
return nullptr;
}
return nullptr;
const std::string tag = release->tag;
const std::string name = release->name;
jobjectArray result = env->NewObjectArray(2, env->FindClass("java/lang/String"), nullptr);
const jstring jtag = env->NewStringUTF(tag.c_str());
const jstring jname = env->NewStringUTF(name.c_str());
env->SetObjectArrayElement(result, 0, jtag);
env->SetObjectArrayElement(result, 1, jname);
env->DeleteLocalRef(jtag);
env->DeleteLocalRef(jname);
return result;
}
JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateUrl(
@ -1640,9 +1664,11 @@ JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateUrl(
JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateApkUrl(
JNIEnv* env,
jobject obj,
jstring version,
jstring tag,
jstring artifact,
jstring packageId) {
const char* version_str = env->GetStringUTFChars(version, nullptr);
const char* version_str = env->GetStringUTFChars(tag, nullptr);
const char* artifact_str = env->GetStringUTFChars(artifact, nullptr);
const char* package_id_str = env->GetStringUTFChars(packageId, nullptr);
std::string variant;
@ -1653,7 +1679,11 @@ JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateApkUrl(
} else if (package_id.find("com.miHoYo.Yuanshen") != std::string::npos) {
variant = "optimized";
} else {
#ifdef ARCHITECTURE_arm64
variant = "standard";
#else
variant = "chromeos";
#endif
}
const std::string apk_filename = fmt::format("Eden-Android-{}-{}.apk", version_str, variant);
@ -1663,7 +1693,7 @@ JNIEXPORT jstring JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_getUpdateApkUrl(
version_str,
apk_filename);
env->ReleaseStringUTFChars(version, version_str);
env->ReleaseStringUTFChars(tag, version_str);
env->ReleaseStringUTFChars(packageId, package_id_str);
return env->NewStringUTF(url.c_str());
}