From 1d60c8b376198b879685e9bf8a9f199a8697a606 Mon Sep 17 00:00:00 2001 From: Yi Jianlong Date: Thu, 11 Dec 2025 22:37:03 +0800 Subject: Add rule for android c++: - Add glue file and jni interface file to target; - Generate android apk package at install stage; - Use adb to run the android app. --- xmake/rules/android/android_install.lua | 92 +++++++++++++++++++++++++++++++++ xmake/rules/android/android_run.lua | 31 +++++++++++ xmake/rules/android/xmake.lua | 54 +++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 xmake/rules/android/android_install.lua create mode 100644 xmake/rules/android/android_run.lua create mode 100644 xmake/rules/android/xmake.lua diff --git a/xmake/rules/android/android_install.lua b/xmake/rules/android/android_install.lua new file mode 100644 index 000000000..5c05ba498 --- /dev/null +++ b/xmake/rules/android/android_install.lua @@ -0,0 +1,92 @@ +function main(target, android_sdk_version, android_manifest, android_res, android_assets, attachedjar, keystore, + keystore_pass, apk_output_path) + local outputpath = path.join("build", "android", "output") + if os.exists(outputpath) then + os.rmdir(outputpath) + end + local outputtemppath = path.join(outputpath, "temp") + os.mkdir(outputtemppath) + local libpath = path.join(outputpath, "lib") + os.mkdir(libpath) + local libarchpath = path.join(libpath, target:arch()) + os.mkdir(libarchpath) + os.cp(path.join(target:installdir(), "lib", "*.so"), libarchpath) + + -- rename to libmain.so + local target_filename = target:filename() + local source_lib = path.join(libarchpath, target_filename) + local dest_lib = path.join(libarchpath, "libmain.so") + if os.exists(source_lib) then + os.mv(source_lib, dest_lib) + else + cprint("${red}can't find source lib " .. source_lib) + exit(1) + end + + import("core.tool.toolchain") + + local toolchain_ndk = toolchain.load("ndk", { + plat = target:plat(), + arch = target:arch() + }) + + -- get ndk + local ndk = path.translate(assert(toolchain_ndk:config("ndk"), "cannot get NDK!")) + + -- get android sdk directory + local android_sdkdir = path.translate(assert(toolchain_ndk:config("android_sdk"), + "please run `xmake f --android_sdk=xxx` to set the android sdk directory!")) + + -- get android build-tools version + local android_build_toolver = assert(toolchain_ndk:config("build_toolver"), + "please run `xmake f --build_toolver=xxx` to set the android build-tools version!") + + local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), + "android.jar") + + local aapt = path.join(android_sdkdir, "build-tools", android_build_toolver, + "aapt" .. (is_host("windows") and ".exe" or "")) + + --------------------------------------- pack resources + local resonly_apk = path.join(outputtemppath, "res_only.apk") + local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} + + if android_res ~= nil and os.exists(android_res) then + table.insert(aapt_argv, "-S") + table.insert(aapt_argv, android_res) + end + + if android_assets ~= nil and os.exists(android_assets) and os.emptydir(android_assets) == false then + table.insert(aapt_argv, "-A") + table.insert(aapt_argv, android_assets) + end + + cprint("${green}[Android][Packing resources]${white} Save to " .. resonly_apk .. "...") + os.vrunv(aapt, aapt_argv) + + --------------------------------------- pack libs + local curdir = os.cd(outputpath) + os.vrunv(aapt, {"add", "temp/res_only.apk", "lib/arm64-v8a/libmain.so"}) + cprint("${green}[Android][Packing library]${white} Adding lib/arm64-v8a/libmain.so to res_only.apk...") + os.cd(curdir) + + --------------------------------------- align apk + local aligned_apk = path.join(outputtemppath, "unsigned.apk") + local zipalign = path.join(android_sdkdir, "build-tools", android_build_toolver, + "zipalign" .. (is_host("windows") and ".exe" or "")) + local zipalign_argv = {"-f", "4", resonly_apk, aligned_apk} + + cprint("${green}[Android][Align apk]${white} Save to " .. aligned_apk .. "...") + os.vrunv(zipalign, zipalign_argv) + + --------------------------------------- sign apk + local final_apk = path.join(apk_output_path, target:basename() .. ".apk") + local apksigner = path.join(android_sdkdir, "build-tools", android_build_toolver, + "apksigner" .. (is_host("windows") and ".bat" or "")) + local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", + final_apk, "--in", aligned_apk} + + cprint("${green}[Android][Signing apk]${white} Save to " .. final_apk .. "...") + os.vrunv(apksigner, apksigner_argv) + +end diff --git a/xmake/rules/android/android_run.lua b/xmake/rules/android/android_run.lua new file mode 100644 index 000000000..d758ba404 --- /dev/null +++ b/xmake/rules/android/android_run.lua @@ -0,0 +1,31 @@ +function main(target, apk_output_path, package_name, activity_name) + import("core.tool.toolchain") + local toolchain_ndk = toolchain.load("ndk", {plat = target:plat(), arch = target:arch()}) + local android_sdkdir = path.translate(toolchain_ndk:config("android_sdk")) + local adb = path.join(android_sdkdir, "platform-tools", "adb" .. (is_host("windows") and ".exe" or "")) + + local outputpath = path.join("build", "android", "output") + local outputtemppath = path.join(outputpath, "temp") + assert(os.exists(outputtemppath)) + + local final_output_path = apk_output_path or outputtemppath + local final_apk = path.join(final_output_path, target:basename() .. ".apk") + assert(os.exists(final_apk)) + + local install_argv = { + "install", final_apk, + } + + cprint("{green}[Installing apk] ...") + os.vrunv(adb, install_argv) + + local run_argv = { + "shell", + "am", + "start", "-n", + package_name .. "/" .. activity_name + } + + cprint("{green}[Run apk] ...") + os.vrunv(adb, run_argv) +end diff --git a/xmake/rules/android/xmake.lua b/xmake/rules/android/xmake.lua new file mode 100644 index 000000000..d83041e25 --- /dev/null +++ b/xmake/rules/android/xmake.lua @@ -0,0 +1,54 @@ +rule("android.cpp") + if is_plat("android") then + on_load(function (target) + import("core.tool.toolchain") + local toolchain_ndk = toolchain.load("ndk", {plat = target:plat(), arch = target:arch()}) + if not toolchain_ndk then + raise("NDK toolchain not found! Please configure NDK properly.") + end + + local ndk_root = toolchain_ndk:config("ndk") + if not ndk_root then + raise("NDK path not set! Please set NDK path properly.") + end + + local native_app_glue_path = path.join(ndk_root, "sources", "android", "native_app_glue") + + -- Add glue file and jni interface file to target + local conf = target:extraconf("rules", "android.cpp") + local jni_inferface = conf.jni_interface + target:add("files", jni_inferface) + target:add("files", path.join(native_app_glue_path, "android_native_app_glue.c")) + target:add("includedirs", native_app_glue_path) + end) + + after_install(function (target) + local conf = target:extraconf("rules", "android.cpp") + local android_sdk_version = conf.android_sdk_version + local android_manifest = conf.android_manifest + local android_res = conf.android_res + local android_assets = conf.android_assets + local keystore = conf.keystore + local keystore_pass = conf.keystore_pass or "123456" + local apk_output_path = conf.apk_output_path or "." + local attachedjar = conf.attachedjar + + assert(android_sdk_version, "android sdk version not set") + assert(android_manifest, "android manifest not set") + + import("android_install")(target, android_sdk_version, android_manifest, android_res, + android_assets, attachedjar, keystore, keystore_pass, apk_output_path) + end) + + on_run(function (target) + local conf = target:extraconf("rules", "android.cpp") + local apk_output_path = conf.apk_output_path or "." + local package_name = conf.package_name + local activity_name = conf.activity_name + + assert(package_name, "package name not set") + assert(activity_name, "activity name not set") + + import("android_run")(target, apk_output_path, package_name, activity_name) + end) + end -- cgit v1.3.1 From 55612e6ab2b5b9c4201845244965aa11c3ffabab Mon Sep 17 00:00:00 2001 From: Yi Jianlong Date: Thu, 11 Dec 2025 23:17:35 +0800 Subject: resolve review comments --- xmake/rules/android/android_install.lua | 7 +++---- xmake/rules/android/android_run.lua | 2 +- xmake/rules/android/xmake.lua | 9 ++++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/xmake/rules/android/android_install.lua b/xmake/rules/android/android_install.lua index 5c05ba498..97b78609b 100644 --- a/xmake/rules/android/android_install.lua +++ b/xmake/rules/android/android_install.lua @@ -19,8 +19,7 @@ function main(target, android_sdk_version, android_manifest, android_res, androi if os.exists(source_lib) then os.mv(source_lib, dest_lib) else - cprint("${red}can't find source lib " .. source_lib) - exit(1) + os.raise("can't find source lib: " .. source_lib) end import("core.tool.toolchain") @@ -66,8 +65,8 @@ function main(target, android_sdk_version, android_manifest, android_res, androi --------------------------------------- pack libs local curdir = os.cd(outputpath) - os.vrunv(aapt, {"add", "temp/res_only.apk", "lib/arm64-v8a/libmain.so"}) - cprint("${green}[Android][Packing library]${white} Adding lib/arm64-v8a/libmain.so to res_only.apk...") + os.vrunv(aapt, {"add", "temp/res_only.apk", path.join("lib", target:arch(), "libmain.so")}) + cprint("${green}[Android][Packing library]${white} Adding lib/" .. target:arch() .. "/libmain.so to res_only.apk...") os.cd(curdir) --------------------------------------- align apk diff --git a/xmake/rules/android/android_run.lua b/xmake/rules/android/android_run.lua index d758ba404..c3c3cbaf8 100644 --- a/xmake/rules/android/android_run.lua +++ b/xmake/rules/android/android_run.lua @@ -1,7 +1,7 @@ function main(target, apk_output_path, package_name, activity_name) import("core.tool.toolchain") local toolchain_ndk = toolchain.load("ndk", {plat = target:plat(), arch = target:arch()}) - local android_sdkdir = path.translate(toolchain_ndk:config("android_sdk")) + local android_sdkdir = path.translate(assert(toolchain_ndk:config("android_sdk"), "please run `xmake f --android_sdk=xxx` to set the android sdk directory!")) local adb = path.join(android_sdkdir, "platform-tools", "adb" .. (is_host("windows") and ".exe" or "")) local outputpath = path.join("build", "android", "output") diff --git a/xmake/rules/android/xmake.lua b/xmake/rules/android/xmake.lua index d83041e25..9b7c05350 100644 --- a/xmake/rules/android/xmake.lua +++ b/xmake/rules/android/xmake.lua @@ -15,9 +15,8 @@ rule("android.cpp") local native_app_glue_path = path.join(ndk_root, "sources", "android", "native_app_glue") -- Add glue file and jni interface file to target - local conf = target:extraconf("rules", "android.cpp") - local jni_inferface = conf.jni_interface - target:add("files", jni_inferface) + local conf = target:extraconf("rules", "android.cpp") + target:add("files", conf.jni_interface) target:add("files", path.join(native_app_glue_path, "android_native_app_glue.c")) target:add("includedirs", native_app_glue_path) end) @@ -28,8 +27,8 @@ rule("android.cpp") local android_manifest = conf.android_manifest local android_res = conf.android_res local android_assets = conf.android_assets - local keystore = conf.keystore - local keystore_pass = conf.keystore_pass or "123456" + local keystore = assert(conf.keystore, "android.cpp rule requires `keystore` to be set") + local keystore_pass = assert(conf.keystore_pass, "android.cpp rule requires `keystore_pass` to be set") local apk_output_path = conf.apk_output_path or "." local attachedjar = conf.attachedjar -- cgit v1.3.1 From 711feadb87c1224de4fa81745d7a13565aeda10d Mon Sep 17 00:00:00 2001 From: Yi Jianlong Date: Thu, 11 Dec 2025 23:21:48 +0800 Subject: update default path --- xmake/rules/android/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/android/xmake.lua b/xmake/rules/android/xmake.lua index 9b7c05350..f46facde4 100644 --- a/xmake/rules/android/xmake.lua +++ b/xmake/rules/android/xmake.lua @@ -29,7 +29,7 @@ rule("android.cpp") local android_assets = conf.android_assets local keystore = assert(conf.keystore, "android.cpp rule requires `keystore` to be set") local keystore_pass = assert(conf.keystore_pass, "android.cpp rule requires `keystore_pass` to be set") - local apk_output_path = conf.apk_output_path or "." + local apk_output_path = conf.apk_output_path or "build" local attachedjar = conf.attachedjar assert(android_sdk_version, "android sdk version not set") -- cgit v1.3.1 From 7298699afb4e2baf50978cda9b2cc8822170301b Mon Sep 17 00:00:00 2001 From: Yi Jianlong Date: Fri, 12 Dec 2025 15:00:44 +0800 Subject: refactor the android native app rule and add a simple test project --- .../c++/ndk_raylib/android/AndroidManifest.xml | 31 +++++++ tests/projects/c++/ndk_raylib/android/debug.jks | Bin 0 -> 2487 bytes .../ndk_raylib/android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../c++/ndk_raylib/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../c++/ndk_raylib/android/res/values/strings.xml | 4 + .../c++/ndk_raylib/android/res/values/styles.xml | 9 ++ tests/projects/c++/ndk_raylib/src/main.cpp | 21 +++++ tests/projects/c++/ndk_raylib/xmake.lua | 22 +++++ xmake/rules/android/android_install.lua | 91 ------------------- xmake/rules/android/android_run.lua | 31 ------- xmake/rules/android/xmake.lua | 53 ----------- xmake/rules/ndk/install.lua | 34 ++++++++ xmake/rules/ndk/load.lua | 42 +++++++++ xmake/rules/ndk/package.lua | 97 +++++++++++++++++++++ xmake/rules/ndk/run.lua | 35 ++++++++ xmake/rules/ndk/xmake.lua | 33 +++++++ 16 files changed, 328 insertions(+), 175 deletions(-) create mode 100644 tests/projects/c++/ndk_raylib/android/AndroidManifest.xml create mode 100644 tests/projects/c++/ndk_raylib/android/debug.jks create mode 100644 tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png create mode 100644 tests/projects/c++/ndk_raylib/android/res/values/strings.xml create mode 100644 tests/projects/c++/ndk_raylib/android/res/values/styles.xml create mode 100644 tests/projects/c++/ndk_raylib/src/main.cpp create mode 100644 tests/projects/c++/ndk_raylib/xmake.lua delete mode 100644 xmake/rules/android/android_install.lua delete mode 100644 xmake/rules/android/android_run.lua delete mode 100644 xmake/rules/android/xmake.lua create mode 100644 xmake/rules/ndk/install.lua create mode 100644 xmake/rules/ndk/load.lua create mode 100644 xmake/rules/ndk/package.lua create mode 100644 xmake/rules/ndk/run.lua create mode 100644 xmake/rules/ndk/xmake.lua diff --git a/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml b/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml new file mode 100644 index 000000000..40cfd7066 --- /dev/null +++ b/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/android/debug.jks b/tests/projects/c++/ndk_raylib/android/debug.jks new file mode 100644 index 000000000..b4eb4f9f2 Binary files /dev/null and b/tests/projects/c++/ndk_raylib/android/debug.jks differ diff --git a/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png b/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png b/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png differ diff --git a/tests/projects/c++/ndk_raylib/android/res/values/strings.xml b/tests/projects/c++/ndk_raylib/android/res/values/strings.xml new file mode 100644 index 000000000..e98a18284 --- /dev/null +++ b/tests/projects/c++/ndk_raylib/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Space Defender + \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/android/res/values/styles.xml b/tests/projects/c++/ndk_raylib/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/c++/ndk_raylib/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/src/main.cpp b/tests/projects/c++/ndk_raylib/src/main.cpp new file mode 100644 index 000000000..4c8253ead --- /dev/null +++ b/tests/projects/c++/ndk_raylib/src/main.cpp @@ -0,0 +1,21 @@ +#include + +int main() { + InitWindow(0, 0, "Hello, xmake for raylib android!"); + + SetTargetFPS(60); + + while (!WindowShouldClose()) { // Main game loop + BeginDrawing(); + + ClearBackground(BLACK); + + DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); + + EndDrawing(); + } + + CloseWindow(); + + return 0; +} \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/xmake.lua b/tests/projects/c++/ndk_raylib/xmake.lua new file mode 100644 index 000000000..08a102d9d --- /dev/null +++ b/tests/projects/c++/ndk_raylib/xmake.lua @@ -0,0 +1,22 @@ +add_rules("mode.debug", "mode.release") + + +add_requires("raylib 5.5.0") + +target("raydemo_android") + set_kind("binary") + set_languages("c++17") + add_files("src/main.cpp") + add_packages("raylib") + + if is_plat("android") then + + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.raylib.demo" + }) + end diff --git a/xmake/rules/android/android_install.lua b/xmake/rules/android/android_install.lua deleted file mode 100644 index 97b78609b..000000000 --- a/xmake/rules/android/android_install.lua +++ /dev/null @@ -1,91 +0,0 @@ -function main(target, android_sdk_version, android_manifest, android_res, android_assets, attachedjar, keystore, - keystore_pass, apk_output_path) - local outputpath = path.join("build", "android", "output") - if os.exists(outputpath) then - os.rmdir(outputpath) - end - local outputtemppath = path.join(outputpath, "temp") - os.mkdir(outputtemppath) - local libpath = path.join(outputpath, "lib") - os.mkdir(libpath) - local libarchpath = path.join(libpath, target:arch()) - os.mkdir(libarchpath) - os.cp(path.join(target:installdir(), "lib", "*.so"), libarchpath) - - -- rename to libmain.so - local target_filename = target:filename() - local source_lib = path.join(libarchpath, target_filename) - local dest_lib = path.join(libarchpath, "libmain.so") - if os.exists(source_lib) then - os.mv(source_lib, dest_lib) - else - os.raise("can't find source lib: " .. source_lib) - end - - import("core.tool.toolchain") - - local toolchain_ndk = toolchain.load("ndk", { - plat = target:plat(), - arch = target:arch() - }) - - -- get ndk - local ndk = path.translate(assert(toolchain_ndk:config("ndk"), "cannot get NDK!")) - - -- get android sdk directory - local android_sdkdir = path.translate(assert(toolchain_ndk:config("android_sdk"), - "please run `xmake f --android_sdk=xxx` to set the android sdk directory!")) - - -- get android build-tools version - local android_build_toolver = assert(toolchain_ndk:config("build_toolver"), - "please run `xmake f --build_toolver=xxx` to set the android build-tools version!") - - local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), - "android.jar") - - local aapt = path.join(android_sdkdir, "build-tools", android_build_toolver, - "aapt" .. (is_host("windows") and ".exe" or "")) - - --------------------------------------- pack resources - local resonly_apk = path.join(outputtemppath, "res_only.apk") - local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} - - if android_res ~= nil and os.exists(android_res) then - table.insert(aapt_argv, "-S") - table.insert(aapt_argv, android_res) - end - - if android_assets ~= nil and os.exists(android_assets) and os.emptydir(android_assets) == false then - table.insert(aapt_argv, "-A") - table.insert(aapt_argv, android_assets) - end - - cprint("${green}[Android][Packing resources]${white} Save to " .. resonly_apk .. "...") - os.vrunv(aapt, aapt_argv) - - --------------------------------------- pack libs - local curdir = os.cd(outputpath) - os.vrunv(aapt, {"add", "temp/res_only.apk", path.join("lib", target:arch(), "libmain.so")}) - cprint("${green}[Android][Packing library]${white} Adding lib/" .. target:arch() .. "/libmain.so to res_only.apk...") - os.cd(curdir) - - --------------------------------------- align apk - local aligned_apk = path.join(outputtemppath, "unsigned.apk") - local zipalign = path.join(android_sdkdir, "build-tools", android_build_toolver, - "zipalign" .. (is_host("windows") and ".exe" or "")) - local zipalign_argv = {"-f", "4", resonly_apk, aligned_apk} - - cprint("${green}[Android][Align apk]${white} Save to " .. aligned_apk .. "...") - os.vrunv(zipalign, zipalign_argv) - - --------------------------------------- sign apk - local final_apk = path.join(apk_output_path, target:basename() .. ".apk") - local apksigner = path.join(android_sdkdir, "build-tools", android_build_toolver, - "apksigner" .. (is_host("windows") and ".bat" or "")) - local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", - final_apk, "--in", aligned_apk} - - cprint("${green}[Android][Signing apk]${white} Save to " .. final_apk .. "...") - os.vrunv(apksigner, apksigner_argv) - -end diff --git a/xmake/rules/android/android_run.lua b/xmake/rules/android/android_run.lua deleted file mode 100644 index c3c3cbaf8..000000000 --- a/xmake/rules/android/android_run.lua +++ /dev/null @@ -1,31 +0,0 @@ -function main(target, apk_output_path, package_name, activity_name) - import("core.tool.toolchain") - local toolchain_ndk = toolchain.load("ndk", {plat = target:plat(), arch = target:arch()}) - local android_sdkdir = path.translate(assert(toolchain_ndk:config("android_sdk"), "please run `xmake f --android_sdk=xxx` to set the android sdk directory!")) - local adb = path.join(android_sdkdir, "platform-tools", "adb" .. (is_host("windows") and ".exe" or "")) - - local outputpath = path.join("build", "android", "output") - local outputtemppath = path.join(outputpath, "temp") - assert(os.exists(outputtemppath)) - - local final_output_path = apk_output_path or outputtemppath - local final_apk = path.join(final_output_path, target:basename() .. ".apk") - assert(os.exists(final_apk)) - - local install_argv = { - "install", final_apk, - } - - cprint("{green}[Installing apk] ...") - os.vrunv(adb, install_argv) - - local run_argv = { - "shell", - "am", - "start", "-n", - package_name .. "/" .. activity_name - } - - cprint("{green}[Run apk] ...") - os.vrunv(adb, run_argv) -end diff --git a/xmake/rules/android/xmake.lua b/xmake/rules/android/xmake.lua deleted file mode 100644 index f46facde4..000000000 --- a/xmake/rules/android/xmake.lua +++ /dev/null @@ -1,53 +0,0 @@ -rule("android.cpp") - if is_plat("android") then - on_load(function (target) - import("core.tool.toolchain") - local toolchain_ndk = toolchain.load("ndk", {plat = target:plat(), arch = target:arch()}) - if not toolchain_ndk then - raise("NDK toolchain not found! Please configure NDK properly.") - end - - local ndk_root = toolchain_ndk:config("ndk") - if not ndk_root then - raise("NDK path not set! Please set NDK path properly.") - end - - local native_app_glue_path = path.join(ndk_root, "sources", "android", "native_app_glue") - - -- Add glue file and jni interface file to target - local conf = target:extraconf("rules", "android.cpp") - target:add("files", conf.jni_interface) - target:add("files", path.join(native_app_glue_path, "android_native_app_glue.c")) - target:add("includedirs", native_app_glue_path) - end) - - after_install(function (target) - local conf = target:extraconf("rules", "android.cpp") - local android_sdk_version = conf.android_sdk_version - local android_manifest = conf.android_manifest - local android_res = conf.android_res - local android_assets = conf.android_assets - local keystore = assert(conf.keystore, "android.cpp rule requires `keystore` to be set") - local keystore_pass = assert(conf.keystore_pass, "android.cpp rule requires `keystore_pass` to be set") - local apk_output_path = conf.apk_output_path or "build" - local attachedjar = conf.attachedjar - - assert(android_sdk_version, "android sdk version not set") - assert(android_manifest, "android manifest not set") - - import("android_install")(target, android_sdk_version, android_manifest, android_res, - android_assets, attachedjar, keystore, keystore_pass, apk_output_path) - end) - - on_run(function (target) - local conf = target:extraconf("rules", "android.cpp") - local apk_output_path = conf.apk_output_path or "." - local package_name = conf.package_name - local activity_name = conf.activity_name - - assert(package_name, "package name not set") - assert(activity_name, "activity name not set") - - import("android_run")(target, apk_output_path, package_name, activity_name) - end) - end diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua new file mode 100644 index 000000000..3a1b04342 --- /dev/null +++ b/xmake/rules/ndk/install.lua @@ -0,0 +1,34 @@ +-- !A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author Xmake Open Source Community +-- @file xmake.lua +-- + +function main(target) + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") + assert(os.exists(final_apk)) + + cprint("${green}[Android][Install] try to install apk ...") + os.vrunv(adb, {"install", final_apk}) + + cprint("${green}[Android][Install] done.") + +end diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua new file mode 100644 index 000000000..5eaee58aa --- /dev/null +++ b/xmake/rules/ndk/load.lua @@ -0,0 +1,42 @@ +-- !A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author Xmake Open Source Community +-- @file xmake.lua +-- + +import("core.tool.toolchain") + +-- main entry +function main (target) + + local toolchain_ndk = target:toolchain("ndk") + + local ndk_root = toolchain_ndk:config("ndk") + if not ndk_root then + raise("NDK path not set! Please set NDK path properly.") + end + + local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") + + -- Add glue file to target + local conf = target:extraconf("rules", "android.native_app") + target:add("files", native_app_glue_file) + target:add("includedirs", native_app_glue_path) + + target:set("kind", "shared") + +end diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua new file mode 100644 index 000000000..227afaaa8 --- /dev/null +++ b/xmake/rules/ndk/package.lua @@ -0,0 +1,97 @@ +-- !A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author Xmake Open Source Community +-- @file xmake.lua +-- + +import("core.tool.toolchain") + +function main(target) + local conf = target:extraconf("rules", "android.native_app") + local android_sdk_version = conf.android_sdk_version + local android_manifest = conf.android_manifest + local android_res = conf.android_res + local android_assets = conf.android_assets + local keystore = conf.keystore + local keystore_pass = conf.keystore_pass + + assert(android_sdk_version, "android sdk version not set") + assert(android_manifest, "android manifest not set") + + cprint("${green}[Android][Package]${white} Starting...") + + local tmp_path = path.join(target:targetdir(), "temp") + os.mkdir(tmp_path) + os.mkdir(path.join(tmp_path, "lib")) + os.mkdir(path.join(tmp_path, "lib", target:arch())) + + -- copy the target library to temp folder with name libmain.so + local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") + os.cp(target:targetfile(), libfile) + + + -- get android tool path + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local android_build_toolver = target:toolchain("ndk"):config("build_toolver") + local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) + + local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) + local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) + local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) + + -- pack resources + local resonly_apk = path.join(tmp_path, "res_only.apk") + local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), + "android.jar") + assert(os.exists(androidjar), "%s not found", androidjar) + local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} + + if android_res ~= nil and os.exists(android_res) then + table.insert(aapt_argv, "-S") + table.insert(aapt_argv, android_res) + end + + if android_assets ~= nil and os.exists(android_assets) and os.emptydir(android_assets) == false then + table.insert(aapt_argv, "-A") + table.insert(aapt_argv, android_assets) + end + + cprint("${green}[Android][Packing resources]${white} Create a resource only apk...") + os.vrunv(aapt, aapt_argv) + + -- pack libs + cprint("${green}[Android][Packing library]${white} Adding library to res_only.apk...") + os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) + + -- align apk + local aligned_apk = path.join(tmp_path, "unsigned.apk") + local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} + + cprint("${green}[Android][Align apk]${white} Save to " .. aligned_apk .. "...") + os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) + + -- sign apk + local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") + + local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", + final_apk, "--in", aligned_apk} + cprint("${green}[Android][Signing apk]${white} Save to " .. final_apk .. "...") + os.vrunv(apksigner, apksigner_argv) + + cprint("${green}[Android][Package]${white} Done!") + +end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua new file mode 100644 index 000000000..08751021a --- /dev/null +++ b/xmake/rules/ndk/run.lua @@ -0,0 +1,35 @@ +-- !A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author Xmake Open Source Community +-- @file xmake.lua +-- + +function main(target) + + local conf = target:extraconf("rules", "android.native_app") + local package_name = conf.package_name + local activity_name = conf.activity_name or "android.app.NativeActivity" + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + local run_argv = {"shell", "am", "start", "-n", package_name .. "/" .. activity_name} + + cprint("${green}[Android] Starting app ...") + os.vrunv(adb, run_argv) + +end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua new file mode 100644 index 000000000..2779a0665 --- /dev/null +++ b/xmake/rules/ndk/xmake.lua @@ -0,0 +1,33 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author Xmake Open Source Community +-- @file xmake.lua +-- + +-- define rule: build android native app with NDK +rule("android.native_app") + -- we must set_kind and add some glue files to target + on_load("load") + + -- generate android apk package + on_package("package") + + -- install android package with adb + on_install("install") + + -- run android app through adb + after_install("run") \ No newline at end of file -- cgit v1.3.1 From 8e63376d62415825aa2836df19ebb7c895aa7a2e Mon Sep 17 00:00:00 2001 From: Yi Jianlong Date: Mon, 15 Dec 2025 10:10:35 +0800 Subject: resolve review comments --- .../android/native_app/android/AndroidManifest.xml | 31 +++++++++++++++++ .../projects/android/native_app/android/debug.jks | Bin 0 -> 2487 bytes .../native_app/android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../android/native_app/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../native_app/android/res/values/strings.xml | 4 +++ .../native_app/android/res/values/styles.xml | 9 +++++ tests/projects/android/native_app/src/main.cpp | 21 ++++++++++++ tests/projects/android/native_app/xmake.lua | 18 ++++++++++ .../c++/ndk_raylib/android/AndroidManifest.xml | 31 ----------------- tests/projects/c++/ndk_raylib/android/debug.jks | Bin 2487 -> 0 bytes .../ndk_raylib/android/res/mipmap-mdpi/icon.png | Bin 2643 -> 0 bytes .../c++/ndk_raylib/android/res/mipmap/icon.png | Bin 2643 -> 0 bytes .../c++/ndk_raylib/android/res/values/strings.xml | 4 --- .../c++/ndk_raylib/android/res/values/styles.xml | 9 ----- tests/projects/c++/ndk_raylib/src/main.cpp | 21 ------------ tests/projects/c++/ndk_raylib/xmake.lua | 22 ------------ xmake/rules/ndk/install.lua | 8 ++--- xmake/rules/ndk/load.lua | 10 ++---- xmake/rules/ndk/package.lua | 38 ++++++++++----------- xmake/rules/ndk/run.lua | 6 ++-- xmake/rules/ndk/xmake.lua | 21 +++++++----- 21 files changed, 123 insertions(+), 130 deletions(-) create mode 100644 tests/projects/android/native_app/android/AndroidManifest.xml create mode 100644 tests/projects/android/native_app/android/debug.jks create mode 100644 tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/android/native_app/android/res/mipmap/icon.png create mode 100644 tests/projects/android/native_app/android/res/values/strings.xml create mode 100644 tests/projects/android/native_app/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/src/main.cpp create mode 100644 tests/projects/android/native_app/xmake.lua delete mode 100644 tests/projects/c++/ndk_raylib/android/AndroidManifest.xml delete mode 100644 tests/projects/c++/ndk_raylib/android/debug.jks delete mode 100644 tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png delete mode 100644 tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png delete mode 100644 tests/projects/c++/ndk_raylib/android/res/values/strings.xml delete mode 100644 tests/projects/c++/ndk_raylib/android/res/values/styles.xml delete mode 100644 tests/projects/c++/ndk_raylib/src/main.cpp delete mode 100644 tests/projects/c++/ndk_raylib/xmake.lua diff --git a/tests/projects/android/native_app/android/AndroidManifest.xml b/tests/projects/android/native_app/android/AndroidManifest.xml new file mode 100644 index 000000000..40cfd7066 --- /dev/null +++ b/tests/projects/android/native_app/android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/android/debug.jks b/tests/projects/android/native_app/android/debug.jks new file mode 100644 index 000000000..b4eb4f9f2 Binary files /dev/null and b/tests/projects/android/native_app/android/debug.jks differ diff --git a/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/android/native_app/android/res/mipmap/icon.png b/tests/projects/android/native_app/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/android/res/mipmap/icon.png differ diff --git a/tests/projects/android/native_app/android/res/values/strings.xml b/tests/projects/android/native_app/android/res/values/strings.xml new file mode 100644 index 000000000..e98a18284 --- /dev/null +++ b/tests/projects/android/native_app/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Space Defender + \ No newline at end of file diff --git a/tests/projects/android/native_app/android/res/values/styles.xml b/tests/projects/android/native_app/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/android/native_app/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/src/main.cpp b/tests/projects/android/native_app/src/main.cpp new file mode 100644 index 000000000..4c8253ead --- /dev/null +++ b/tests/projects/android/native_app/src/main.cpp @@ -0,0 +1,21 @@ +#include + +int main() { + InitWindow(0, 0, "Hello, xmake for raylib android!"); + + SetTargetFPS(60); + + while (!WindowShouldClose()) { // Main game loop + BeginDrawing(); + + ClearBackground(BLACK); + + DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); + + EndDrawing(); + } + + CloseWindow(); + + return 0; +} \ No newline at end of file diff --git a/tests/projects/android/native_app/xmake.lua b/tests/projects/android/native_app/xmake.lua new file mode 100644 index 000000000..81ac545e5 --- /dev/null +++ b/tests/projects/android/native_app/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.debug", "mode.release") + +add_requires("raylib 5.5.0") + +target("raydemo_android") + set_kind("binary") + set_languages("c++17") + add_files("src/main.cpp") + add_packages("raylib") + + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.raylib.demo" + }) diff --git a/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml b/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml deleted file mode 100644 index 40cfd7066..000000000 --- a/tests/projects/c++/ndk_raylib/android/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/android/debug.jks b/tests/projects/c++/ndk_raylib/android/debug.jks deleted file mode 100644 index b4eb4f9f2..000000000 Binary files a/tests/projects/c++/ndk_raylib/android/debug.jks and /dev/null differ diff --git a/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png b/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png deleted file mode 100644 index 743413831..000000000 Binary files a/tests/projects/c++/ndk_raylib/android/res/mipmap-mdpi/icon.png and /dev/null differ diff --git a/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png b/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png deleted file mode 100644 index 743413831..000000000 Binary files a/tests/projects/c++/ndk_raylib/android/res/mipmap/icon.png and /dev/null differ diff --git a/tests/projects/c++/ndk_raylib/android/res/values/strings.xml b/tests/projects/c++/ndk_raylib/android/res/values/strings.xml deleted file mode 100644 index e98a18284..000000000 --- a/tests/projects/c++/ndk_raylib/android/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Space Defender - \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/android/res/values/styles.xml b/tests/projects/c++/ndk_raylib/android/res/values/styles.xml deleted file mode 100644 index 621547380..000000000 --- a/tests/projects/c++/ndk_raylib/android/res/values/styles.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/src/main.cpp b/tests/projects/c++/ndk_raylib/src/main.cpp deleted file mode 100644 index 4c8253ead..000000000 --- a/tests/projects/c++/ndk_raylib/src/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include - -int main() { - InitWindow(0, 0, "Hello, xmake for raylib android!"); - - SetTargetFPS(60); - - while (!WindowShouldClose()) { // Main game loop - BeginDrawing(); - - ClearBackground(BLACK); - - DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); - - EndDrawing(); - } - - CloseWindow(); - - return 0; -} \ No newline at end of file diff --git a/tests/projects/c++/ndk_raylib/xmake.lua b/tests/projects/c++/ndk_raylib/xmake.lua deleted file mode 100644 index 08a102d9d..000000000 --- a/tests/projects/c++/ndk_raylib/xmake.lua +++ /dev/null @@ -1,22 +0,0 @@ -add_rules("mode.debug", "mode.release") - - -add_requires("raylib 5.5.0") - -target("raydemo_android") - set_kind("binary") - set_languages("c++17") - add_files("src/main.cpp") - add_packages("raylib") - - if is_plat("android") then - - add_rules("android.native_app", { - android_sdk_version = "35", - android_manifest = "android/AndroidManifest.xml", - android_res = "android/res", - keystore = "android/debug.jks", - keystore_pass = "123456", - package_name = "com.raylib.demo" - }) - end diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 3a1b04342..8dae64ccd 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -14,8 +14,8 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author Xmake Open Source Community --- @file xmake.lua +-- @author keosu +-- @file install.lua -- function main(target) @@ -26,9 +26,9 @@ function main(target) local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") assert(os.exists(final_apk)) - cprint("${green}[Android][Install] try to install apk ...") + cprint("${color.success}[Android][Install] try to install apk ...") os.vrunv(adb, {"install", final_apk}) - cprint("${green}[Android][Install] done.") + cprint("${color.success}[Android][Install] done.") end diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua index 5eaee58aa..8119c31a2 100644 --- a/xmake/rules/ndk/load.lua +++ b/xmake/rules/ndk/load.lua @@ -14,12 +14,10 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author Xmake Open Source Community --- @file xmake.lua +-- @author keosu +-- @file load.lua -- -import("core.tool.toolchain") - -- main entry function main (target) @@ -30,10 +28,8 @@ function main (target) raise("NDK path not set! Please set NDK path properly.") end - local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") - -- Add glue file to target - local conf = target:extraconf("rules", "android.native_app") + local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") target:add("files", native_app_glue_file) target:add("includedirs", native_app_glue_path) diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 227afaaa8..795b87d0d 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -14,14 +14,13 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author Xmake Open Source Community --- @file xmake.lua +-- @author keosu +-- @file package.lua -- - import("core.tool.toolchain") function main(target) - local conf = target:extraconf("rules", "android.native_app") + local conf = target:extraconf("rules", "android.native_app") local android_sdk_version = conf.android_sdk_version local android_manifest = conf.android_manifest local android_res = conf.android_res @@ -32,66 +31,65 @@ function main(target) assert(android_sdk_version, "android sdk version not set") assert(android_manifest, "android manifest not set") - cprint("${green}[Android][Package]${white} Starting...") + cprint("${color.success}[Android][Package]${clear} Starting...") local tmp_path = path.join(target:targetdir(), "temp") - os.mkdir(tmp_path) - os.mkdir(path.join(tmp_path, "lib")) + os.mkdir(tmp_path) + os.mkdir(path.join(tmp_path, "lib")) os.mkdir(path.join(tmp_path, "lib", target:arch())) -- copy the target library to temp folder with name libmain.so local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") os.cp(target:targetfile(), libfile) - -- get android tool path local android_sdkdir = target:toolchain("ndk"):config("android_sdk") local android_build_toolver = target:toolchain("ndk"):config("build_toolver") local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) - local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) + local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) -- pack resources - local resonly_apk = path.join(tmp_path, "res_only.apk") + local resonly_apk = path.join(tmp_path, "res_only.apk") local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), "android.jar") assert(os.exists(androidjar), "%s not found", androidjar) local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} - if android_res ~= nil and os.exists(android_res) then + if android_res and not os.emptydir(android_res) then table.insert(aapt_argv, "-S") table.insert(aapt_argv, android_res) end - if android_assets ~= nil and os.exists(android_assets) and os.emptydir(android_assets) == false then + if android_assets and not os.emptydir(android_assets) then table.insert(aapt_argv, "-A") table.insert(aapt_argv, android_assets) end - cprint("${green}[Android][Packing resources]${white} Create a resource only apk...") + cprint("${color.success}[Android][Packing resources]${clear} Create a resource only apk...") os.vrunv(aapt, aapt_argv) -- pack libs - cprint("${green}[Android][Packing library]${white} Adding library to res_only.apk...") + cprint("${color.success}[Android][Packing library]${clear} Adding library to res_only.apk...") os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) -- align apk - local aligned_apk = path.join(tmp_path, "unsigned.apk") + local aligned_apk = path.join(tmp_path, "unsigned.apk") local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} - cprint("${green}[Android][Align apk]${white} Save to " .. aligned_apk .. "...") - os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) + cprint("${color.success}[Android][Align apk]${clear} Save to " .. aligned_apk .. "...") + os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) -- sign apk local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", final_apk, "--in", aligned_apk} - cprint("${green}[Android][Signing apk]${white} Save to " .. final_apk .. "...") + cprint("${color.success}[Android][Signing apk]${clear} Save to " .. final_apk .. "...") os.vrunv(apksigner, apksigner_argv) - cprint("${green}[Android][Package]${white} Done!") - + cprint("${color.success}[Android][Package]${clear} Done!") + end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index 08751021a..1c08099bd 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -14,8 +14,8 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author Xmake Open Source Community --- @file xmake.lua +-- @author keosu +-- @file run.lua -- function main(target) @@ -29,7 +29,7 @@ function main(target) local run_argv = {"shell", "am", "start", "-n", package_name .. "/" .. activity_name} - cprint("${green}[Android] Starting app ...") + cprint("${color.success}[Android] Starting app ...") os.vrunv(adb, run_argv) end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua index 2779a0665..313c57c05 100644 --- a/xmake/rules/ndk/xmake.lua +++ b/xmake/rules/ndk/xmake.lua @@ -14,20 +14,23 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author Xmake Open Source Community +-- @author keosu -- @file xmake.lua -- -- define rule: build android native app with NDK rule("android.native_app") - -- we must set_kind and add some glue files to target - on_load("load") + -- this rule only for android target + if is_plat("android") then + -- we must set_kind and add some glue files to target + on_load("load") - -- generate android apk package - on_package("package") + -- generate android apk package + on_package("package") - -- install android package with adb - on_install("install") + -- install android package with adb + on_install("install") - -- run android app through adb - after_install("run") \ No newline at end of file + -- run android app through adb + after_install("run") + end \ No newline at end of file -- cgit v1.3.1 From c9ede56339f7faf96bb6ed105fd60dfcaf01655f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:25:49 +0800 Subject: format code and fix keystore --- .../projects/android/native_app/android/debug.jks | Bin 2487 -> 2148 bytes tests/projects/android/native_app/src/main.cpp | 33 +++++++++------------ tests/projects/android/native_app/xmake.lua | 3 +- xmake/rules/ndk/install.lua | 6 ++-- xmake/rules/ndk/load.lua | 18 +++++++---- xmake/rules/ndk/package.lua | 9 ++++-- xmake/rules/ndk/run.lua | 6 ++-- xmake/rules/ndk/xmake.lua | 20 ++++++------- 8 files changed, 48 insertions(+), 47 deletions(-) diff --git a/tests/projects/android/native_app/android/debug.jks b/tests/projects/android/native_app/android/debug.jks index b4eb4f9f2..0a18aa012 100644 Binary files a/tests/projects/android/native_app/android/debug.jks and b/tests/projects/android/native_app/android/debug.jks differ diff --git a/tests/projects/android/native_app/src/main.cpp b/tests/projects/android/native_app/src/main.cpp index 4c8253ead..42f5b9a37 100644 --- a/tests/projects/android/native_app/src/main.cpp +++ b/tests/projects/android/native_app/src/main.cpp @@ -1,21 +1,16 @@ #include -int main() { - InitWindow(0, 0, "Hello, xmake for raylib android!"); - - SetTargetFPS(60); - - while (!WindowShouldClose()) { // Main game loop - BeginDrawing(); - - ClearBackground(BLACK); - - DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); - - EndDrawing(); - } - - CloseWindow(); - - return 0; -} \ No newline at end of file +int main(int argc, char** argv) { + InitWindow(0, 0, "Hello, xmake for raylib android!"); + SetTargetFPS(60); + + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(BLACK); + DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); + EndDrawing(); + } + + CloseWindow(); + return 0; +} diff --git a/tests/projects/android/native_app/xmake.lua b/tests/projects/android/native_app/xmake.lua index 81ac545e5..e959fdf32 100644 --- a/tests/projects/android/native_app/xmake.lua +++ b/tests/projects/android/native_app/xmake.lua @@ -5,9 +5,8 @@ add_requires("raylib 5.5.0") target("raydemo_android") set_kind("binary") set_languages("c++17") - add_files("src/main.cpp") + add_files("src/main.cpp") add_packages("raylib") - add_rules("android.native_app", { android_sdk_version = "35", android_manifest = "android/AndroidManifest.xml", diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 8dae64ccd..6ab137c89 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -1,4 +1,4 @@ --- !A cross-platform build utility based on Lua +--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. @@ -18,17 +18,17 @@ -- @file install.lua -- +-- main entry function main(target) local android_sdkdir = target:toolchain("ndk"):config("android_sdk") local adb = path.join(android_sdkdir, "platform-tools", "adb") local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - assert(os.exists(final_apk)) + assert(os.exists(final_apk)) cprint("${color.success}[Android][Install] try to install apk ...") os.vrunv(adb, {"install", final_apk}) cprint("${color.success}[Android][Install] done.") - end diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua index 8119c31a2..fbb7b72c8 100644 --- a/xmake/rules/ndk/load.lua +++ b/xmake/rules/ndk/load.lua @@ -1,4 +1,4 @@ --- !A cross-platform build utility based on Lua +--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. @@ -19,20 +19,26 @@ -- -- main entry -function main (target) +function main(target) - local toolchain_ndk = target:toolchain("ndk") + -- only for android target + if not target:is_plat("android") then + wprint("rule(android.native_app): only for android system!") + target:rule_enable("android.native_app", false) + return + end + local toolchain_ndk = target:toolchain("ndk") local ndk_root = toolchain_ndk:config("ndk") if not ndk_root then raise("NDK path not set! Please set NDK path properly.") end - -- Add glue file to target + -- add glue file to target local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") + local native_app_glue_dir = path.directory(native_app_glue_file) target:add("files", native_app_glue_file) - target:add("includedirs", native_app_glue_path) + target:add("includedirs", native_app_glue_dir) target:set("kind", "shared") - end diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 795b87d0d..6583ee0a0 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -1,4 +1,4 @@ --- !A cross-platform build utility based on Lua +--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. @@ -17,9 +17,13 @@ -- @author keosu -- @file package.lua -- + +-- imports import("core.tool.toolchain") +-- main entry function main(target) + local conf = target:extraconf("rules", "android.native_app") local android_sdk_version = conf.android_sdk_version local android_manifest = conf.android_manifest @@ -51,7 +55,7 @@ function main(target) local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) - -- pack resources + -- pack resources local resonly_apk = path.join(tmp_path, "res_only.apk") local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), "android.jar") @@ -91,5 +95,4 @@ function main(target) os.vrunv(apksigner, apksigner_argv) cprint("${color.success}[Android][Package]${clear} Done!") - end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index 1c08099bd..d4ab85be5 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -1,4 +1,4 @@ --- !A cross-platform build utility based on Lua +--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. @@ -18,9 +18,10 @@ -- @file run.lua -- +-- main entry function main(target) - local conf = target:extraconf("rules", "android.native_app") + local conf = target:extraconf("rules", "android.native_app") local package_name = conf.package_name local activity_name = conf.activity_name or "android.app.NativeActivity" @@ -31,5 +32,4 @@ function main(target) cprint("${color.success}[Android] Starting app ...") os.vrunv(adb, run_argv) - end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua index 313c57c05..4e97dc3fc 100644 --- a/xmake/rules/ndk/xmake.lua +++ b/xmake/rules/ndk/xmake.lua @@ -20,17 +20,15 @@ -- define rule: build android native app with NDK rule("android.native_app") - -- this rule only for android target - if is_plat("android") then - -- we must set_kind and add some glue files to target - on_load("load") - -- generate android apk package - on_package("package") + -- we must set_kind and add some glue files to target + on_load("load") - -- install android package with adb - on_install("install") + -- generate android apk package + on_package("package") - -- run android app through adb - after_install("run") - end \ No newline at end of file + -- install android package with adb + on_install("install") + + -- run android app through adb + after_install("run") -- cgit v1.3.1 From c92d42d463b2593c31baa53769ab2951af545329 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:28:16 +0800 Subject: improve ndk rules --- xmake/rules/ndk/install.lua | 9 +++++++-- xmake/rules/ndk/load.lua | 4 ++-- xmake/rules/ndk/package.lua | 13 +++++-------- xmake/rules/ndk/run.lua | 2 +- xmake/rules/ndk/uninstall.lua | 33 +++++++++++++++++++++++++++++++++ xmake/rules/ndk/xmake.lua | 20 +++++++++++++++++++- 6 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 xmake/rules/ndk/uninstall.lua diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 6ab137c89..092562ccf 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -18,6 +18,9 @@ -- @file install.lua -- +-- imports +import("run", {alias = "run_app"}) + -- main entry function main(target) @@ -27,8 +30,10 @@ function main(target) local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") assert(os.exists(final_apk)) - cprint("${color.success}[Android][Install] try to install apk ...") + cprint("installing %s ...", final_apk) os.vrunv(adb, {"install", final_apk}) + cprint("install ok") - cprint("${color.success}[Android][Install] done.") + -- run it + run_app(target) end diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua index fbb7b72c8..766994bb9 100644 --- a/xmake/rules/ndk/load.lua +++ b/xmake/rules/ndk/load.lua @@ -34,11 +34,11 @@ function main(target) raise("NDK path not set! Please set NDK path properly.") end + target:set("kind", "shared") + -- add glue file to target local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") local native_app_glue_dir = path.directory(native_app_glue_file) target:add("files", native_app_glue_file) target:add("includedirs", native_app_glue_dir) - - target:set("kind", "shared") end diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 6583ee0a0..171d697e5 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -35,8 +35,6 @@ function main(target) assert(android_sdk_version, "android sdk version not set") assert(android_manifest, "android manifest not set") - cprint("${color.success}[Android][Package]${clear} Starting...") - local tmp_path = path.join(target:targetdir(), "temp") os.mkdir(tmp_path) os.mkdir(path.join(tmp_path, "lib")) @@ -72,18 +70,18 @@ function main(target) table.insert(aapt_argv, android_assets) end - cprint("${color.success}[Android][Packing resources]${clear} Create a resource only apk...") + cprint("packing resources ...") os.vrunv(aapt, aapt_argv) -- pack libs - cprint("${color.success}[Android][Packing library]${clear} Adding library to res_only.apk...") + cprint("packing library ...") os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) -- align apk local aligned_apk = path.join(tmp_path, "unsigned.apk") local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} - cprint("${color.success}[Android][Align apk]${clear} Save to " .. aligned_apk .. "...") + cprint("aligning apk ...") os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) -- sign apk @@ -91,8 +89,7 @@ function main(target) local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", final_apk, "--in", aligned_apk} - cprint("${color.success}[Android][Signing apk]${clear} Save to " .. final_apk .. "...") + cprint("packing %s ...", final_apk) os.vrunv(apksigner, apksigner_argv) - - cprint("${color.success}[Android][Package]${clear} Done!") + cprint("pack ok") end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index d4ab85be5..d85af1de9 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -30,6 +30,6 @@ function main(target) local run_argv = {"shell", "am", "start", "-n", package_name .. "/" .. activity_name} - cprint("${color.success}[Android] Starting app ...") + cprint("running %s ...", package_name) os.vrunv(adb, run_argv) end diff --git a/xmake/rules/ndk/uninstall.lua b/xmake/rules/ndk/uninstall.lua new file mode 100644 index 000000000..821ce69bd --- /dev/null +++ b/xmake/rules/ndk/uninstall.lua @@ -0,0 +1,33 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file uninstall.lua +-- + +-- main entry +function main(target) + + local conf = target:extraconf("rules", "android.native_app") + local package_name = conf.package_name + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + cprint("uninstalling %s ...", package_name) + os.vrunv(adb, {"uninstall", package_name}) + cprint("uninstall ok") +end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua index 4e97dc3fc..5de5c8ad9 100644 --- a/xmake/rules/ndk/xmake.lua +++ b/xmake/rules/ndk/xmake.lua @@ -19,6 +19,21 @@ -- -- define rule: build android native app with NDK +-- +-- @code +-- target("test") +-- set_kind("binary") +-- add_rules("android.native_app", { +-- android_sdk_version = "35", +-- android_manifest = "android/AndroidManifest.xml", +-- android_res = "android/res", +-- android_assets = "android/assets", +-- keystore = "android/debug.jks", +-- keystore_pass = "123456", +-- package_name = "com.raylib.demo" +-- }) +-- @endcode +-- rule("android.native_app") -- we must set_kind and add some glue files to target @@ -30,5 +45,8 @@ rule("android.native_app") -- install android package with adb on_install("install") + -- uninstall android package with adb + on_uninstall("uninstall") + -- run android app through adb - after_install("run") + on_run("run") -- cgit v1.3.1 From b0f05a5196bb5c4b0590895e69c64fd1a2be3f9c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:30:38 +0800 Subject: improve check logs --- xmake/rules/ndk/install.lua | 5 +++-- xmake/rules/ndk/package.lua | 13 +++++-------- xmake/rules/ndk/xmake.lua | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 092562ccf..20f213f05 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.tool.toolchain") import("run", {alias = "run_app"}) -- main entry @@ -28,10 +29,10 @@ function main(target) local adb = path.join(android_sdkdir, "platform-tools", "adb") local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - assert(os.exists(final_apk)) + assert(os.isfile(final_apk), "apk file %s not found!", final_apk) cprint("installing %s ...", final_apk) - os.vrunv(adb, {"install", final_apk}) + os.vrunv(adb, {"install", "-r", final_apk}) cprint("install ok") -- run it diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 171d697e5..5b4921ddb 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -20,9 +20,10 @@ -- imports import("core.tool.toolchain") +import("utils.progress") -- main entry -function main(target) +function main(target, opt) local conf = target:extraconf("rules", "android.native_app") local android_sdk_version = conf.android_sdk_version @@ -35,6 +36,9 @@ function main(target) assert(android_sdk_version, "android sdk version not set") assert(android_manifest, "android manifest not set") + local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") + progress.show(opt.progress, "${color.build.target}packing.apk %s", final_apk) + local tmp_path = path.join(target:targetdir(), "temp") os.mkdir(tmp_path) os.mkdir(path.join(tmp_path, "lib")) @@ -70,26 +74,19 @@ function main(target) table.insert(aapt_argv, android_assets) end - cprint("packing resources ...") os.vrunv(aapt, aapt_argv) -- pack libs - cprint("packing library ...") os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) -- align apk local aligned_apk = path.join(tmp_path, "unsigned.apk") local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} - cprint("aligning apk ...") os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) -- sign apk - local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", final_apk, "--in", aligned_apk} - cprint("packing %s ...", final_apk) os.vrunv(apksigner, apksigner_argv) - cprint("pack ok") end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua index 5de5c8ad9..783abac65 100644 --- a/xmake/rules/ndk/xmake.lua +++ b/xmake/rules/ndk/xmake.lua @@ -40,7 +40,7 @@ rule("android.native_app") on_load("load") -- generate android apk package - on_package("package") + after_build("package") -- install android package with adb on_install("install") -- cgit v1.3.1 From 51ef6420b6bba35a34f3ac9dafd5b5d36eb24e2d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:33:30 +0800 Subject: improve run logs --- tests/projects/android/native_app/src/main.cpp | 5 +++++ tests/projects/android/native_app/xmake.lua | 4 +++- xmake/rules/ndk/install.lua | 1 - xmake/rules/ndk/package.lua | 1 - xmake/rules/ndk/run.lua | 18 ++++++++++++++++++ xmake/rules/ndk/xmake.lua | 3 ++- 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/projects/android/native_app/src/main.cpp b/tests/projects/android/native_app/src/main.cpp index 42f5b9a37..b7dda5d34 100644 --- a/tests/projects/android/native_app/src/main.cpp +++ b/tests/projects/android/native_app/src/main.cpp @@ -1,8 +1,13 @@ #include +#include + +#define LOG_TAG "raydemo_android" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) int main(int argc, char** argv) { InitWindow(0, 0, "Hello, xmake for raylib android!"); SetTargetFPS(60); + LOGI("raylib application is running!"); while (!WindowShouldClose()) { BeginDrawing(); diff --git a/tests/projects/android/native_app/xmake.lua b/tests/projects/android/native_app/xmake.lua index e959fdf32..587994928 100644 --- a/tests/projects/android/native_app/xmake.lua +++ b/tests/projects/android/native_app/xmake.lua @@ -6,6 +6,7 @@ target("raydemo_android") set_kind("binary") set_languages("c++17") add_files("src/main.cpp") + add_syslinks("log") add_packages("raylib") add_rules("android.native_app", { android_sdk_version = "35", @@ -13,5 +14,6 @@ target("raydemo_android") android_res = "android/res", keystore = "android/debug.jks", keystore_pass = "123456", - package_name = "com.raylib.demo" + package_name = "com.raylib.demo", + logcat_filters = {"raydemo_android", "raylib"} }) diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 20f213f05..672a623ce 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -19,7 +19,6 @@ -- -- imports -import("core.tool.toolchain") import("run", {alias = "run_app"}) -- main entry diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 5b4921ddb..797efa22e 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -19,7 +19,6 @@ -- -- imports -import("core.tool.toolchain") import("utils.progress") -- main entry diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index d85af1de9..612d18c7e 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -18,6 +18,9 @@ -- @file run.lua -- +-- imports +import("core.base.tty") + -- main entry function main(target) @@ -32,4 +35,19 @@ function main(target) cprint("running %s ...", package_name) os.vrunv(adb, run_argv) + + -- show logcat + local logcat_argv = {"logcat"} + if io.isatty() and (tty.has_color8() or tty.has_color256()) then + table.insert(logcat_argv, "-v") + table.insert(logcat_argv, "color") + end + local logcat_filters = conf.logcat_filters + if logcat_filters then + table.insert(logcat_argv, "-s") + for _, filter in ipairs(logcat_filters) do + table.insert(logcat_argv, filter) + end + end + os.execv(adb, logcat_argv) end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua index 783abac65..0c58d7d09 100644 --- a/xmake/rules/ndk/xmake.lua +++ b/xmake/rules/ndk/xmake.lua @@ -30,7 +30,8 @@ -- android_assets = "android/assets", -- keystore = "android/debug.jks", -- keystore_pass = "123456", --- package_name = "com.raylib.demo" +-- package_name = "com.raylib.demo", +-- logcat_filters = {"raydemo_android", "raylib"} -- }) -- @endcode -- -- cgit v1.3.1 From fb8a3f6b216638783cd25600a02f7527dabd91cf Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:36:36 +0800 Subject: improve logs tag --- tests/projects/android/native_app/src/main.cpp | 2 +- tests/projects/android/native_app/xmake.lua | 2 +- xmake/rules/ndk/load.lua | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/projects/android/native_app/src/main.cpp b/tests/projects/android/native_app/src/main.cpp index b7dda5d34..e906f490e 100644 --- a/tests/projects/android/native_app/src/main.cpp +++ b/tests/projects/android/native_app/src/main.cpp @@ -1,7 +1,7 @@ #include #include -#define LOG_TAG "raydemo_android" +#define LOG_TAG "raydemo" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) int main(int argc, char** argv) { diff --git a/tests/projects/android/native_app/xmake.lua b/tests/projects/android/native_app/xmake.lua index 587994928..f5fc5f2ed 100644 --- a/tests/projects/android/native_app/xmake.lua +++ b/tests/projects/android/native_app/xmake.lua @@ -2,7 +2,7 @@ add_rules("mode.debug", "mode.release") add_requires("raylib 5.5.0") -target("raydemo_android") +target("raydemo") set_kind("binary") set_languages("c++17") add_files("src/main.cpp") diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua index 766994bb9..7700f85e7 100644 --- a/xmake/rules/ndk/load.lua +++ b/xmake/rules/ndk/load.lua @@ -34,6 +34,7 @@ function main(target) raise("NDK path not set! Please set NDK path properly.") end + -- set target kind target:set("kind", "shared") -- add glue file to target -- cgit v1.3.1 From 5537af295c452f1bbc1875c27b285a35a167f44e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:37:27 +0800 Subject: add incbuild support --- xmake/rules/ndk/package.lua | 103 +++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 797efa22e..076c78217 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.project.depend") import("utils.progress") -- main entry @@ -36,56 +37,68 @@ function main(target, opt) assert(android_manifest, "android manifest not set") local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - progress.show(opt.progress, "${color.build.target}packing.apk %s", final_apk) - - local tmp_path = path.join(target:targetdir(), "temp") - os.mkdir(tmp_path) - os.mkdir(path.join(tmp_path, "lib")) - os.mkdir(path.join(tmp_path, "lib", target:arch())) - - -- copy the target library to temp folder with name libmain.so - local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") - os.cp(target:targetfile(), libfile) - - -- get android tool path - local android_sdkdir = target:toolchain("ndk"):config("android_sdk") - local android_build_toolver = target:toolchain("ndk"):config("build_toolver") - local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) - - local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) - local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) - local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) - - -- pack resources - local resonly_apk = path.join(tmp_path, "res_only.apk") - local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), - "android.jar") - assert(os.exists(androidjar), "%s not found", androidjar) - local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} - - if android_res and not os.emptydir(android_res) then - table.insert(aapt_argv, "-S") - table.insert(aapt_argv, android_res) - end - if android_assets and not os.emptydir(android_assets) then - table.insert(aapt_argv, "-A") - table.insert(aapt_argv, android_assets) + -- add dependencies + local depfiles = {target:targetfile(), android_manifest, keystore} + if android_res and os.isdir(android_res) then + table.join2(depfiles, os.files(path.join(android_res, "**"))) + end + if android_assets and os.isdir(android_assets) then + table.join2(depfiles, os.files(path.join(android_assets, "**"))) end - os.vrunv(aapt, aapt_argv) + depend.on_changed(function () + progress.show(opt.progress, "${color.build.target}packing.apk %s", final_apk) + + local tmp_path = path.join(target:targetdir(), "temp") + os.mkdir(tmp_path) + os.mkdir(path.join(tmp_path, "lib")) + os.mkdir(path.join(tmp_path, "lib", target:arch())) + + -- copy the target library to temp folder with name libmain.so + local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") + os.cp(target:targetfile(), libfile) + + -- get android tool path + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local android_build_toolver = target:toolchain("ndk"):config("build_toolver") + local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) + + local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) + local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) + local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) + + -- pack resources + local resonly_apk = path.join(tmp_path, "res_only.apk") + local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), + "android.jar") + assert(os.exists(androidjar), "%s not found", androidjar) + local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} + + if android_res and not os.emptydir(android_res) then + table.insert(aapt_argv, "-S") + table.insert(aapt_argv, android_res) + end + + if android_assets and not os.emptydir(android_assets) then + table.insert(aapt_argv, "-A") + table.insert(aapt_argv, android_assets) + end + + os.vrunv(aapt, aapt_argv) - -- pack libs - os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) + -- pack libs + os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) - -- align apk - local aligned_apk = path.join(tmp_path, "unsigned.apk") - local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} + -- align apk + local aligned_apk = path.join(tmp_path, "unsigned.apk") + local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} - os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) + os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) - -- sign apk - local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", - final_apk, "--in", aligned_apk} - os.vrunv(apksigner, apksigner_argv) + -- sign apk + local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", + final_apk, "--in", aligned_apk} + os.vrunv(apksigner, apksigner_argv) + end, {dependfile = target:dependfile(final_apk), files = depfiles, values = {android_sdk_version, keystore_pass}}) end -- cgit v1.3.1 From 3e7d8b94f1a1349ccbae107b5a2aeac9fb77e6e2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:39:52 +0800 Subject: improve raylib tests --- .../android/native_app/android/AndroidManifest.xml | 31 -------- .../projects/android/native_app/android/debug.jks | Bin 2148 -> 0 bytes .../native_app/android/res/mipmap-mdpi/icon.png | Bin 2643 -> 0 bytes .../android/native_app/android/res/mipmap/icon.png | Bin 2643 -> 0 bytes .../native_app/android/res/values/strings.xml | 4 - .../native_app/android/res/values/styles.xml | 9 --- .../raylib_basic/android/AndroidManifest.xml | 31 ++++++++ .../native_app/raylib_basic/android/debug.jks | Bin 0 -> 2148 bytes .../raylib_basic/android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../raylib_basic/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../raylib_basic/android/res/values/strings.xml | 4 + .../raylib_basic/android/res/values/styles.xml | 9 +++ .../android/native_app/raylib_basic/src/main.cpp | 21 ++++++ .../android/native_app/raylib_basic/xmake.lua | 19 +++++ .../raylib_particles/android/AndroidManifest.xml | 31 ++++++++ .../native_app/raylib_particles/android/debug.jks | Bin 0 -> 2148 bytes .../android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../raylib_particles/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../android/res/values/strings.xml | 4 + .../raylib_particles/android/res/values/styles.xml | 9 +++ .../native_app/raylib_particles/src/main.cpp | 81 +++++++++++++++++++++ .../android/native_app/raylib_particles/xmake.lua | 19 +++++ tests/projects/android/native_app/src/main.cpp | 21 ------ tests/projects/android/native_app/xmake.lua | 19 ----- 24 files changed, 228 insertions(+), 84 deletions(-) delete mode 100644 tests/projects/android/native_app/android/AndroidManifest.xml delete mode 100644 tests/projects/android/native_app/android/debug.jks delete mode 100644 tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png delete mode 100644 tests/projects/android/native_app/android/res/mipmap/icon.png delete mode 100644 tests/projects/android/native_app/android/res/values/strings.xml delete mode 100644 tests/projects/android/native_app/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/raylib_basic/android/AndroidManifest.xml create mode 100644 tests/projects/android/native_app/raylib_basic/android/debug.jks create mode 100644 tests/projects/android/native_app/raylib_basic/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/android/native_app/raylib_basic/android/res/mipmap/icon.png create mode 100644 tests/projects/android/native_app/raylib_basic/android/res/values/strings.xml create mode 100644 tests/projects/android/native_app/raylib_basic/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/raylib_basic/src/main.cpp create mode 100644 tests/projects/android/native_app/raylib_basic/xmake.lua create mode 100644 tests/projects/android/native_app/raylib_particles/android/AndroidManifest.xml create mode 100644 tests/projects/android/native_app/raylib_particles/android/debug.jks create mode 100644 tests/projects/android/native_app/raylib_particles/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/android/native_app/raylib_particles/android/res/mipmap/icon.png create mode 100644 tests/projects/android/native_app/raylib_particles/android/res/values/strings.xml create mode 100644 tests/projects/android/native_app/raylib_particles/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/raylib_particles/src/main.cpp create mode 100644 tests/projects/android/native_app/raylib_particles/xmake.lua delete mode 100644 tests/projects/android/native_app/src/main.cpp delete mode 100644 tests/projects/android/native_app/xmake.lua diff --git a/tests/projects/android/native_app/android/AndroidManifest.xml b/tests/projects/android/native_app/android/AndroidManifest.xml deleted file mode 100644 index 40cfd7066..000000000 --- a/tests/projects/android/native_app/android/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/projects/android/native_app/android/debug.jks b/tests/projects/android/native_app/android/debug.jks deleted file mode 100644 index 0a18aa012..000000000 Binary files a/tests/projects/android/native_app/android/debug.jks and /dev/null differ diff --git a/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png deleted file mode 100644 index 743413831..000000000 Binary files a/tests/projects/android/native_app/android/res/mipmap-mdpi/icon.png and /dev/null differ diff --git a/tests/projects/android/native_app/android/res/mipmap/icon.png b/tests/projects/android/native_app/android/res/mipmap/icon.png deleted file mode 100644 index 743413831..000000000 Binary files a/tests/projects/android/native_app/android/res/mipmap/icon.png and /dev/null differ diff --git a/tests/projects/android/native_app/android/res/values/strings.xml b/tests/projects/android/native_app/android/res/values/strings.xml deleted file mode 100644 index e98a18284..000000000 --- a/tests/projects/android/native_app/android/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Space Defender - \ No newline at end of file diff --git a/tests/projects/android/native_app/android/res/values/styles.xml b/tests/projects/android/native_app/android/res/values/styles.xml deleted file mode 100644 index 621547380..000000000 --- a/tests/projects/android/native_app/android/res/values/styles.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_basic/android/AndroidManifest.xml b/tests/projects/android/native_app/raylib_basic/android/AndroidManifest.xml new file mode 100644 index 000000000..2d6b2d67c --- /dev/null +++ b/tests/projects/android/native_app/raylib_basic/android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_basic/android/debug.jks b/tests/projects/android/native_app/raylib_basic/android/debug.jks new file mode 100644 index 000000000..0a18aa012 Binary files /dev/null and b/tests/projects/android/native_app/raylib_basic/android/debug.jks differ diff --git a/tests/projects/android/native_app/raylib_basic/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/raylib_basic/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/raylib_basic/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/android/native_app/raylib_basic/android/res/mipmap/icon.png b/tests/projects/android/native_app/raylib_basic/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/raylib_basic/android/res/mipmap/icon.png differ diff --git a/tests/projects/android/native_app/raylib_basic/android/res/values/strings.xml b/tests/projects/android/native_app/raylib_basic/android/res/values/strings.xml new file mode 100644 index 000000000..bc0a9bfbf --- /dev/null +++ b/tests/projects/android/native_app/raylib_basic/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Raylib Basic + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_basic/android/res/values/styles.xml b/tests/projects/android/native_app/raylib_basic/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/android/native_app/raylib_basic/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_basic/src/main.cpp b/tests/projects/android/native_app/raylib_basic/src/main.cpp new file mode 100644 index 000000000..b160499b7 --- /dev/null +++ b/tests/projects/android/native_app/raylib_basic/src/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +#define LOG_TAG "raydemo_basic" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) + +int main(int argc, char** argv) { + InitWindow(0, 0, "Hello, xmake for raylib android!"); + SetTargetFPS(60); + LOGI("raylib application is running!"); + + while (!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(BLACK); + DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); + EndDrawing(); + } + + CloseWindow(); + return 0; +} diff --git a/tests/projects/android/native_app/raylib_basic/xmake.lua b/tests/projects/android/native_app/raylib_basic/xmake.lua new file mode 100644 index 000000000..50886764d --- /dev/null +++ b/tests/projects/android/native_app/raylib_basic/xmake.lua @@ -0,0 +1,19 @@ +add_rules("mode.debug", "mode.release") + +add_requires("raylib 5.5.0") + +target("raydemo_basic") + set_kind("binary") + set_languages("c++17") + add_files("src/main.cpp") + add_syslinks("log") + add_packages("raylib") + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.raylib.basic", + logcat_filters = {"raydemo_basic", "raylib"} + }) diff --git a/tests/projects/android/native_app/raylib_particles/android/AndroidManifest.xml b/tests/projects/android/native_app/raylib_particles/android/AndroidManifest.xml new file mode 100644 index 000000000..70dd36933 --- /dev/null +++ b/tests/projects/android/native_app/raylib_particles/android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_particles/android/debug.jks b/tests/projects/android/native_app/raylib_particles/android/debug.jks new file mode 100644 index 000000000..0a18aa012 Binary files /dev/null and b/tests/projects/android/native_app/raylib_particles/android/debug.jks differ diff --git a/tests/projects/android/native_app/raylib_particles/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/raylib_particles/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/raylib_particles/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/android/native_app/raylib_particles/android/res/mipmap/icon.png b/tests/projects/android/native_app/raylib_particles/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/raylib_particles/android/res/mipmap/icon.png differ diff --git a/tests/projects/android/native_app/raylib_particles/android/res/values/strings.xml b/tests/projects/android/native_app/raylib_particles/android/res/values/strings.xml new file mode 100644 index 000000000..3967cc312 --- /dev/null +++ b/tests/projects/android/native_app/raylib_particles/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Raylib Particles + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_particles/android/res/values/styles.xml b/tests/projects/android/native_app/raylib_particles/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/android/native_app/raylib_particles/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/raylib_particles/src/main.cpp b/tests/projects/android/native_app/raylib_particles/src/main.cpp new file mode 100644 index 000000000..41dd8bd4a --- /dev/null +++ b/tests/projects/android/native_app/raylib_particles/src/main.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#define LOG_TAG "raydemo_particles" +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) + +struct Particle { + Vector2 position; + Vector2 velocity; + Color color; + float size; + float life; +}; + +int main(int argc, char** argv) { + InitWindow(0, 0, "Raylib Particles"); + SetTargetFPS(60); + LOGD("raylib particles starting!"); + + std::vector particles; + + while (!WindowShouldClose()) { + // Update + bool inputActive = IsMouseButtonDown(MOUSE_BUTTON_LEFT) || GetTouchPointCount() > 0; + Vector2 pos; + + if (inputActive) { + pos = GetMousePosition(); + if (GetTouchPointCount() > 0) pos = GetTouchPosition(0); + } else { + // Auto emit when idle + double time = GetTime(); + pos.x = GetScreenWidth() / 2.0f + cos(time * 3.0f) * (GetScreenWidth() / 4.0f); + pos.y = GetScreenHeight() / 2.0f + sin(time * 2.0f) * (GetScreenHeight() / 4.0f); + } + + if (inputActive || GetRandomValue(0, 100) < 50) { + int count = inputActive ? 5 : 2; + for (int i = 0; i < count; i++) { + Particle p; + p.position = pos; + p.velocity = {(float)GetRandomValue(-200, 200) / 100.0f, (float)GetRandomValue(-200, 200) / 100.0f}; + p.color = (Color){(unsigned char)GetRandomValue(0, 255), (unsigned char)GetRandomValue(0, 255), (unsigned char)GetRandomValue(0, 255), 255}; + p.size = (float)GetRandomValue(5, 20); + p.life = 1.0f; + particles.push_back(p); + } + } + + for (auto it = particles.begin(); it != particles.end();) { + it->position.x += it->velocity.x * 5.0f; + it->position.y += it->velocity.y * 5.0f; + it->life -= 0.02f; + it->size *= 0.99f; + + if (it->life <= 0) { + it = particles.erase(it); + } else { + ++it; + } + } + + // Draw + BeginDrawing(); + ClearBackground(BLACK); + + for (const auto& p : particles) { + DrawCircleV(p.position, p.size, Fade(p.color, p.life)); + } + + DrawText("Touch to create particles!", 10, 40, 20, WHITE); + DrawFPS(10, 10); + + EndDrawing(); + } + + CloseWindow(); + return 0; +} diff --git a/tests/projects/android/native_app/raylib_particles/xmake.lua b/tests/projects/android/native_app/raylib_particles/xmake.lua new file mode 100644 index 000000000..c6d9a6217 --- /dev/null +++ b/tests/projects/android/native_app/raylib_particles/xmake.lua @@ -0,0 +1,19 @@ +add_rules("mode.debug", "mode.release") + +add_requires("raylib 5.5.0") + +target("raydemo_particles") + set_kind("binary") + set_languages("c++17") + add_files("src/main.cpp") + add_syslinks("log") + add_packages("raylib") + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.raylib.particles", + logcat_filters = {"raydemo_particles", "raylib"} + }) diff --git a/tests/projects/android/native_app/src/main.cpp b/tests/projects/android/native_app/src/main.cpp deleted file mode 100644 index e906f490e..000000000 --- a/tests/projects/android/native_app/src/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -#define LOG_TAG "raydemo" -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) - -int main(int argc, char** argv) { - InitWindow(0, 0, "Hello, xmake for raylib android!"); - SetTargetFPS(60); - LOGI("raylib application is running!"); - - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(BLACK); - DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); - EndDrawing(); - } - - CloseWindow(); - return 0; -} diff --git a/tests/projects/android/native_app/xmake.lua b/tests/projects/android/native_app/xmake.lua deleted file mode 100644 index f5fc5f2ed..000000000 --- a/tests/projects/android/native_app/xmake.lua +++ /dev/null @@ -1,19 +0,0 @@ -add_rules("mode.debug", "mode.release") - -add_requires("raylib 5.5.0") - -target("raydemo") - set_kind("binary") - set_languages("c++17") - add_files("src/main.cpp") - add_syslinks("log") - add_packages("raylib") - add_rules("android.native_app", { - android_sdk_version = "35", - android_manifest = "android/AndroidManifest.xml", - android_res = "android/res", - keystore = "android/debug.jks", - keystore_pass = "123456", - package_name = "com.raylib.demo", - logcat_filters = {"raydemo_android", "raylib"} - }) -- cgit v1.3.1 From 427f50fa45d7015bd443fa2c0d059593c826d43f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:40:36 +0800 Subject: improve tests --- tests/projects/android/native_app/raylib_basic/src/main.cpp | 13 ++++++++++++- .../android/native_app/raylib_particles/src/main.cpp | 12 ++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/projects/android/native_app/raylib_basic/src/main.cpp b/tests/projects/android/native_app/raylib_basic/src/main.cpp index b160499b7..0094d9e3c 100644 --- a/tests/projects/android/native_app/raylib_basic/src/main.cpp +++ b/tests/projects/android/native_app/raylib_basic/src/main.cpp @@ -12,7 +12,18 @@ int main(int argc, char** argv) { while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(BLACK); - DrawText("Hello, xmake for raylib android!", 250, 250, 25, BLUE); + + // Draw FPS + const char* fpsText = TextFormat("%2i FPS", GetFPS()); + int fpsWidth = MeasureText(fpsText, 40); + DrawText(fpsText, GetScreenWidth() / 2 - fpsWidth / 2, 30, 40, GREEN); + + // Draw centered text + int fontSize = 50; + const char* text = "Hello, xmake for raylib android!"; + int textWidth = MeasureText(text, fontSize); + DrawText(text, GetScreenWidth() / 2 - textWidth / 2, 100, fontSize, BLUE); + EndDrawing(); } diff --git a/tests/projects/android/native_app/raylib_particles/src/main.cpp b/tests/projects/android/native_app/raylib_particles/src/main.cpp index 41dd8bd4a..5bbfc90e8 100644 --- a/tests/projects/android/native_app/raylib_particles/src/main.cpp +++ b/tests/projects/android/native_app/raylib_particles/src/main.cpp @@ -70,8 +70,16 @@ int main(int argc, char** argv) { DrawCircleV(p.position, p.size, Fade(p.color, p.life)); } - DrawText("Touch to create particles!", 10, 40, 20, WHITE); - DrawFPS(10, 10); + // Draw FPS + const char* fpsText = TextFormat("%2i FPS", GetFPS()); + int fpsWidth = MeasureText(fpsText, 40); + DrawText(fpsText, GetScreenWidth() / 2 - fpsWidth / 2, 30, 40, GREEN); + + // Draw centered instructions + int fontSize = 40; + const char* text = "Touch to create particles!"; + int textWidth = MeasureText(text, fontSize); + DrawText(text, GetScreenWidth() / 2 - textWidth / 2, 80, fontSize, WHITE); EndDrawing(); } -- cgit v1.3.1 From 4efa9f8afc8982fb7ae2f388c9417ae97199ec0a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:41:38 +0800 Subject: fix run script --- xmake/actions/run/main.lua | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua index 94c7d7d6b..6cfe09d3a 100644 --- a/xmake/actions/run/main.lua +++ b/xmake/actions/run/main.lua @@ -145,6 +145,18 @@ function _run(target) os.setenvs(oldenvs) end +-- check if the target is runnable +function _is_runnable(target) + if target:is_binary() or target:script("run") then + return true + end + for _, r in ipairs(target:orderules()) do + if r:script("run") then + return true + end + end +end + -- check targets function _check_targets(targetname, group_pattern) @@ -155,7 +167,7 @@ function _check_targets(targetname, group_pattern) table.insert(targets, target) else for _, target in ipairs(project.ordertargets()) do - if target:is_binary() or target:script("run") then + if _is_runnable(target) then local group = target:get("group") if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then table.insert(targets, target) @@ -216,7 +228,7 @@ function main() else local targets = {} for _, target in ipairs(project.ordertargets()) do - if target:is_binary() or target:script("run") then + if _is_runnable(target) then local group = target:get("group") if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then table.insert(targets, target) -- cgit v1.3.1 From db1900b7a76b6bb59e3780d4377080ef74afa2d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:43:08 +0800 Subject: improve run and install --- xmake/rules/ndk/install.lua | 4 ---- xmake/rules/ndk/run.lua | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 672a623ce..0aa43e790 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -19,7 +19,6 @@ -- -- imports -import("run", {alias = "run_app"}) -- main entry function main(target) @@ -33,7 +32,4 @@ function main(target) cprint("installing %s ...", final_apk) os.vrunv(adb, {"install", "-r", final_apk}) cprint("install ok") - - -- run it - run_app(target) end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index 612d18c7e..b705498d1 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -20,10 +20,14 @@ -- imports import("core.base.tty") +import("install", {alias = "install_app"}) -- main entry function main(target) + -- install it first + install_app(target) + local conf = target:extraconf("rules", "android.native_app") local package_name = conf.package_name local activity_name = conf.activity_name or "android.app.NativeActivity" -- cgit v1.3.1 From 22b299efd13de014023a652bb49f312d4d394c91 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:44:11 +0800 Subject: use os.isfile --- xmake/rules/ndk/install.lua | 1 - xmake/rules/ndk/load.lua | 1 - xmake/rules/ndk/package.lua | 3 +-- xmake/rules/ndk/run.lua | 1 - xmake/rules/ndk/uninstall.lua | 3 +-- 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua index 0aa43e790..ec340ac00 100644 --- a/xmake/rules/ndk/install.lua +++ b/xmake/rules/ndk/install.lua @@ -20,7 +20,6 @@ -- imports --- main entry function main(target) local android_sdkdir = target:toolchain("ndk"):config("android_sdk") diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua index 7700f85e7..3e49d9533 100644 --- a/xmake/rules/ndk/load.lua +++ b/xmake/rules/ndk/load.lua @@ -18,7 +18,6 @@ -- @file load.lua -- --- main entry function main(target) -- only for android target diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua index 076c78217..00142a85f 100644 --- a/xmake/rules/ndk/package.lua +++ b/xmake/rules/ndk/package.lua @@ -22,7 +22,6 @@ import("core.project.depend") import("utils.progress") --- main entry function main(target, opt) local conf = target:extraconf("rules", "android.native_app") @@ -72,7 +71,7 @@ function main(target, opt) local resonly_apk = path.join(tmp_path, "res_only.apk") local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), "android.jar") - assert(os.exists(androidjar), "%s not found", androidjar) + assert(os.isfile(androidjar), "%s not found", androidjar) local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} if android_res and not os.emptydir(android_res) then diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua index b705498d1..657dad4e8 100644 --- a/xmake/rules/ndk/run.lua +++ b/xmake/rules/ndk/run.lua @@ -22,7 +22,6 @@ import("core.base.tty") import("install", {alias = "install_app"}) --- main entry function main(target) -- install it first diff --git a/xmake/rules/ndk/uninstall.lua b/xmake/rules/ndk/uninstall.lua index 821ce69bd..24564d631 100644 --- a/xmake/rules/ndk/uninstall.lua +++ b/xmake/rules/ndk/uninstall.lua @@ -14,11 +14,10 @@ -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- --- @author keosu +-- @author ruki -- @file uninstall.lua -- --- main entry function main(target) local conf = target:extraconf("rules", "android.native_app") -- cgit v1.3.1 From 858fd30a65ac524600e5d3c35539d9204fbea73e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:49:50 +0800 Subject: add lvgl tests --- .../lvgl_basic/android/AndroidManifest.xml | 30 +++ .../native_app/lvgl_basic/android/debug.jks | Bin 0 -> 2148 bytes .../lvgl_basic/android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../lvgl_basic/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../lvgl_basic/android/res/values/strings.xml | 4 + .../lvgl_basic/android/res/values/styles.xml | 9 + .../android/native_app/lvgl_basic/src/main.c | 153 +++++++++++++ .../android/native_app/lvgl_basic/xmake.lua | 23 ++ .../lvgl_particles/android/AndroidManifest.xml | 30 +++ .../native_app/lvgl_particles/android/debug.jks | Bin 0 -> 2148 bytes .../android/res/mipmap-mdpi/icon.png | Bin 0 -> 2643 bytes .../lvgl_particles/android/res/mipmap/icon.png | Bin 0 -> 2643 bytes .../lvgl_particles/android/res/values/strings.xml | 4 + .../lvgl_particles/android/res/values/styles.xml | 9 + .../android/native_app/lvgl_particles/src/main.c | 244 +++++++++++++++++++++ .../android/native_app/lvgl_particles/xmake.lua | 23 ++ 16 files changed, 529 insertions(+) create mode 100644 tests/projects/android/native_app/lvgl_basic/android/AndroidManifest.xml create mode 100644 tests/projects/android/native_app/lvgl_basic/android/debug.jks create mode 100644 tests/projects/android/native_app/lvgl_basic/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/android/native_app/lvgl_basic/android/res/mipmap/icon.png create mode 100644 tests/projects/android/native_app/lvgl_basic/android/res/values/strings.xml create mode 100644 tests/projects/android/native_app/lvgl_basic/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/lvgl_basic/src/main.c create mode 100644 tests/projects/android/native_app/lvgl_basic/xmake.lua create mode 100644 tests/projects/android/native_app/lvgl_particles/android/AndroidManifest.xml create mode 100644 tests/projects/android/native_app/lvgl_particles/android/debug.jks create mode 100644 tests/projects/android/native_app/lvgl_particles/android/res/mipmap-mdpi/icon.png create mode 100644 tests/projects/android/native_app/lvgl_particles/android/res/mipmap/icon.png create mode 100644 tests/projects/android/native_app/lvgl_particles/android/res/values/strings.xml create mode 100644 tests/projects/android/native_app/lvgl_particles/android/res/values/styles.xml create mode 100644 tests/projects/android/native_app/lvgl_particles/src/main.c create mode 100644 tests/projects/android/native_app/lvgl_particles/xmake.lua diff --git a/tests/projects/android/native_app/lvgl_basic/android/AndroidManifest.xml b/tests/projects/android/native_app/lvgl_basic/android/AndroidManifest.xml new file mode 100644 index 000000000..98c3d3795 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_basic/android/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_basic/android/debug.jks b/tests/projects/android/native_app/lvgl_basic/android/debug.jks new file mode 100644 index 000000000..0a18aa012 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_basic/android/debug.jks differ diff --git a/tests/projects/android/native_app/lvgl_basic/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/lvgl_basic/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_basic/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/android/native_app/lvgl_basic/android/res/mipmap/icon.png b/tests/projects/android/native_app/lvgl_basic/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_basic/android/res/mipmap/icon.png differ diff --git a/tests/projects/android/native_app/lvgl_basic/android/res/values/strings.xml b/tests/projects/android/native_app/lvgl_basic/android/res/values/strings.xml new file mode 100644 index 000000000..7dc865540 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_basic/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Lvgl Basic + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_basic/android/res/values/styles.xml b/tests/projects/android/native_app/lvgl_basic/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_basic/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_basic/src/main.c b/tests/projects/android/native_app/lvgl_basic/src/main.c new file mode 100644 index 000000000..56518a22a --- /dev/null +++ b/tests/projects/android/native_app/lvgl_basic/src/main.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "lvgl_basic" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) + +static lv_display_t * display = NULL; +static ANativeWindow * native_window = NULL; +static int32_t window_width = 0; +static int32_t window_height = 0; + +static bool touch_down = false; +static int32_t touch_x = 0; +static int32_t touch_y = 0; + +static void my_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) { + if (!native_window) { + lv_display_flush_ready(disp); + return; + } + + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(native_window, &buffer, NULL) < 0) { + lv_display_flush_ready(disp); + return; + } + + int32_t width = lv_area_get_width(area); + int32_t height = lv_area_get_height(area); + + // Assume 32-bit RGBA + uint32_t * dst_base = (uint32_t *)buffer.bits; + uint32_t * src = (uint32_t *)px_map; + int stride = buffer.stride; + + for (int y = 0; y < height; y++) { + uint32_t * dst_line = dst_base + (area->y1 + y) * stride + area->x1; + memcpy(dst_line, src + y * width, width * sizeof(uint32_t)); + } + + ANativeWindow_unlockAndPost(native_window); + lv_display_flush_ready(disp); +} + +static void my_input_read(lv_indev_t * indev, lv_indev_data_t * data) { + data->point.x = touch_x; + data->point.y = touch_y; + data->state = touch_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; +} + +static void create_ui(void) { + lv_obj_t * label = lv_label_create(lv_screen_active()); + lv_label_set_text(label, "Hello Xmake + LVGL!"); + lv_obj_set_style_text_font(label, &lv_font_montserrat_14, 0); + lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); + + // FPS label + lv_obj_t * label_fps = lv_label_create(lv_screen_active()); + lv_label_set_text(label_fps, "FPS: 0"); + lv_obj_set_style_text_font(label_fps, &lv_font_montserrat_14, 0); + lv_obj_align(label_fps, LV_ALIGN_TOP_MID, 0, 100); +} + +static void handle_cmd(struct android_app* app, int32_t cmd) { + switch (cmd) { + case APP_CMD_INIT_WINDOW: + LOGI("Init Window"); + native_window = app->window; + window_width = ANativeWindow_getWidth(native_window); + window_height = ANativeWindow_getHeight(native_window); + ANativeWindow_setBuffersGeometry(native_window, window_width, window_height, WINDOW_FORMAT_RGBA_8888); + + if (!display) { + display = lv_display_create(window_width, window_height); + lv_display_set_color_format(display, LV_COLOR_FORMAT_ARGB8888); + lv_display_set_flush_cb(display, my_flush_cb); + + size_t buf_size = window_width * window_height * 4; + void * buf = malloc(buf_size); + lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); + + lv_indev_t * indev = lv_indev_create(); + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, my_input_read); + + create_ui(); + } else { + lv_display_set_resolution(display, window_width, window_height); + lv_obj_invalidate(lv_scr_act()); + } + break; + case APP_CMD_TERM_WINDOW: + native_window = NULL; + break; + } +} + +static int32_t handle_input(struct android_app* app, AInputEvent* event) { + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { + int action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; + touch_x = AMotionEvent_getX(event, 0); + touch_y = AMotionEvent_getY(event, 0); + if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) { + touch_down = true; + } else { + touch_down = false; + } + return 1; + } + return 0; +} + +void android_main(struct android_app* app) { + lv_init(); + + app->onAppCmd = handle_cmd; + app->onInputEvent = handle_input; + + int frame_count = 0; + time_t last_time = time(NULL); + + while (1) { + int ident; + int events; + struct android_poll_source* source; + + uint32_t timeout = lv_timer_handler(); + if (timeout > 50) timeout = 50; + + while ((ident = ALooper_pollAll(timeout, NULL, &events, (void**)&source)) >= 0) { + if (source != NULL) source->process(app, source); + if (app->destroyRequested != 0) return; + } + + lv_tick_inc(timeout); + + frame_count++; + time_t current_time = time(NULL); + if (current_time - last_time >= 1) { + lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps + if (label_fps) { + lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); + } + frame_count = 0; + last_time = current_time; + } + } +} diff --git a/tests/projects/android/native_app/lvgl_basic/xmake.lua b/tests/projects/android/native_app/lvgl_basic/xmake.lua new file mode 100644 index 000000000..659d04f45 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_basic/xmake.lua @@ -0,0 +1,23 @@ +add_rules("mode.debug", "mode.release") + +add_requires("lvgl 9.1.0") + +target("lvgl_basic") + set_kind("binary") + set_languages("c99") + add_files("src/main.c") + add_syslinks("log", "android", "EGL", "GLESv2") + add_packages("lvgl") + + -- define LV_CONF_INCLUDE_SIMPLE to include lv_conf.h + add_defines("LV_CONF_INCLUDE_SIMPLE") + + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.lvgl.basic", + logcat_filters = {"lvgl_basic", "lvgl"} + }) diff --git a/tests/projects/android/native_app/lvgl_particles/android/AndroidManifest.xml b/tests/projects/android/native_app/lvgl_particles/android/AndroidManifest.xml new file mode 100644 index 000000000..16d614e95 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_particles/android/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_particles/android/debug.jks b/tests/projects/android/native_app/lvgl_particles/android/debug.jks new file mode 100644 index 000000000..0a18aa012 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_particles/android/debug.jks differ diff --git a/tests/projects/android/native_app/lvgl_particles/android/res/mipmap-mdpi/icon.png b/tests/projects/android/native_app/lvgl_particles/android/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_particles/android/res/mipmap-mdpi/icon.png differ diff --git a/tests/projects/android/native_app/lvgl_particles/android/res/mipmap/icon.png b/tests/projects/android/native_app/lvgl_particles/android/res/mipmap/icon.png new file mode 100644 index 000000000..743413831 Binary files /dev/null and b/tests/projects/android/native_app/lvgl_particles/android/res/mipmap/icon.png differ diff --git a/tests/projects/android/native_app/lvgl_particles/android/res/values/strings.xml b/tests/projects/android/native_app/lvgl_particles/android/res/values/strings.xml new file mode 100644 index 000000000..0c86996ef --- /dev/null +++ b/tests/projects/android/native_app/lvgl_particles/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Lvgl Particles + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_particles/android/res/values/styles.xml b/tests/projects/android/native_app/lvgl_particles/android/res/values/styles.xml new file mode 100644 index 000000000..621547380 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_particles/android/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/tests/projects/android/native_app/lvgl_particles/src/main.c b/tests/projects/android/native_app/lvgl_particles/src/main.c new file mode 100644 index 000000000..0d34298e4 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_particles/src/main.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "lvgl_particles" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) + +static lv_display_t * display = NULL; +static ANativeWindow * native_window = NULL; +static int32_t window_width = 0; +static int32_t window_height = 0; + +static bool touch_down = false; +static int32_t touch_x = 0; +static int32_t touch_y = 0; + +static void my_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) { + if (!native_window) { + lv_display_flush_ready(disp); + return; + } + + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(native_window, &buffer, NULL) < 0) { + lv_display_flush_ready(disp); + return; + } + + int32_t width = lv_area_get_width(area); + int32_t height = lv_area_get_height(area); + + // Assume 32-bit RGBA + uint32_t * dst_base = (uint32_t *)buffer.bits; + uint32_t * src = (uint32_t *)px_map; + int stride = buffer.stride; + + for (int y = 0; y < height; y++) { + uint32_t * dst_line = dst_base + (area->y1 + y) * stride + area->x1; + memcpy(dst_line, src + y * width, width * sizeof(uint32_t)); + } + + ANativeWindow_unlockAndPost(native_window); + lv_display_flush_ready(disp); +} + +static void my_input_read(lv_indev_t * indev, lv_indev_data_t * data) { + data->point.x = touch_x; + data->point.y = touch_y; + data->state = touch_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; +} + +#include + +typedef struct { + int32_t x; + int32_t y; + int32_t vx; + int32_t vy; + lv_color_t color; + int32_t size; + int32_t life; +} Particle; + +#define MAX_PARTICLES 100 +static Particle particles[MAX_PARTICLES]; +static int particle_count = 0; + +static void create_particle(int32_t x, int32_t y) { + if (particle_count < MAX_PARTICLES) { + Particle *p = &particles[particle_count++]; + p->x = x; + p->y = y; + p->vx = (rand() % 10) - 5; + p->vy = (rand() % 10) - 5; + p->color = lv_color_make(rand() % 255, rand() % 255, rand() % 255); + p->size = (rand() % 15) + 5; + p->life = 100; + } +} + +static void update_particles(void) { + for (int i = 0; i < particle_count; i++) { + Particle *p = &particles[i]; + p->x += p->vx; + p->y += p->vy; + p->life--; + + if (p->life <= 0 || p->x < 0 || p->x > window_width || p->y < 0 || p->y > window_height) { + *p = particles[--particle_count]; + i--; + } + } +} + +static void draw_particles(lv_layer_t * layer) { + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + draw_dsc.radius = LV_RADIUS_CIRCLE; + + for (int i = 0; i < particle_count; i++) { + Particle *p = &particles[i]; + draw_dsc.bg_color = p->color; + draw_dsc.bg_opa = (p->life * 255) / 100; + + lv_area_t area; + area.x1 = p->x - p->size / 2; + area.y1 = p->y - p->size / 2; + area.x2 = area.x1 + p->size; + area.y2 = area.y1 + p->size; + + lv_draw_rect(layer, &draw_dsc, &area); + } +} + +static void particle_timer_cb(lv_timer_t * timer) { + if (touch_down) { + for (int i = 0; i < 5; i++) { + create_particle(touch_x, touch_y); + } + } else { + // Auto emit + static float t = 0; + t += 0.1f; + int cx = window_width / 2 + cos(t) * (window_width / 4); + int cy = window_height / 2 + sin(t) * (window_height / 4); + create_particle(cx, cy); + } + + update_particles(); + lv_obj_invalidate(lv_scr_act()); // Force redraw +} + +static void canvas_draw_event_cb(lv_event_t * e) { + lv_layer_t * layer = lv_event_get_layer(e); + draw_particles(layer); +} + +static void create_ui(void) { + lv_obj_t * label = lv_label_create(lv_screen_active()); + lv_label_set_text(label, "Touch to create particles!"); + lv_obj_set_style_text_font(label, &lv_font_montserrat_14, 0); + lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); + + // FPS label + lv_obj_t * label_fps = lv_label_create(lv_screen_active()); + lv_label_set_text(label_fps, "FPS: 0"); + lv_obj_set_style_text_font(label_fps, &lv_font_montserrat_14, 0); + lv_obj_align(label_fps, LV_ALIGN_TOP_MID, 0, 100); + + // Add draw event to screen for particles + lv_obj_add_event_cb(lv_screen_active(), canvas_draw_event_cb, LV_EVENT_DRAW_POST, NULL); + + lv_timer_create(particle_timer_cb, 16, NULL); +} + +static void handle_cmd(struct android_app* app, int32_t cmd) { + switch (cmd) { + case APP_CMD_INIT_WINDOW: + LOGI("Init Window"); + native_window = app->window; + window_width = ANativeWindow_getWidth(native_window); + window_height = ANativeWindow_getHeight(native_window); + ANativeWindow_setBuffersGeometry(native_window, window_width, window_height, WINDOW_FORMAT_RGBA_8888); + + if (!display) { + display = lv_display_create(window_width, window_height); + lv_display_set_color_format(display, LV_COLOR_FORMAT_ARGB8888); + lv_display_set_flush_cb(display, my_flush_cb); + + size_t buf_size = window_width * window_height * 4; + void * buf = malloc(buf_size); + lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); + + lv_indev_t * indev = lv_indev_create(); + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, my_input_read); + + create_ui(); + } else { + lv_display_set_resolution(display, window_width, window_height); + lv_obj_invalidate(lv_scr_act()); + } + break; + case APP_CMD_TERM_WINDOW: + native_window = NULL; + break; + } +} + +static int32_t handle_input(struct android_app* app, AInputEvent* event) { + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { + int action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; + touch_x = AMotionEvent_getX(event, 0); + touch_y = AMotionEvent_getY(event, 0); + if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) { + touch_down = true; + } else { + touch_down = false; + } + return 1; + } + return 0; +} + +void android_main(struct android_app* app) { + lv_init(); + + app->onAppCmd = handle_cmd; + app->onInputEvent = handle_input; + + int frame_count = 0; + time_t last_time = time(NULL); + + while (1) { + int ident; + int events; + struct android_poll_source* source; + + uint32_t timeout = lv_timer_handler(); + if (timeout > 50) timeout = 50; + + while ((ident = ALooper_pollAll(timeout, NULL, &events, (void**)&source)) >= 0) { + if (source != NULL) source->process(app, source); + if (app->destroyRequested != 0) return; + } + + lv_tick_inc(timeout); + + frame_count++; + time_t current_time = time(NULL); + if (current_time - last_time >= 1) { + lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps + if (label_fps) { + lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); + } + frame_count = 0; + last_time = current_time; + } + } +} diff --git a/tests/projects/android/native_app/lvgl_particles/xmake.lua b/tests/projects/android/native_app/lvgl_particles/xmake.lua new file mode 100644 index 000000000..3a74e8439 --- /dev/null +++ b/tests/projects/android/native_app/lvgl_particles/xmake.lua @@ -0,0 +1,23 @@ +add_rules("mode.debug", "mode.release") + +add_requires("lvgl 9.1.0") + +target("lvgl_particles") + set_kind("binary") + set_languages("c99") + add_files("src/main.c") + add_syslinks("log", "android", "EGL", "GLESv2") + add_packages("lvgl") + + -- define LV_CONF_INCLUDE_SIMPLE to include lv_conf.h + add_defines("LV_CONF_INCLUDE_SIMPLE") + + add_rules("android.native_app", { + android_sdk_version = "35", + android_manifest = "android/AndroidManifest.xml", + android_res = "android/res", + keystore = "android/debug.jks", + keystore_pass = "123456", + package_name = "com.lvgl.particles", + logcat_filters = {"lvgl_particles", "lvgl"} + }) -- cgit v1.3.1 From f9c398cb56d74f4f2cd3d9f0b6f07626de65ce5e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:50:36 +0800 Subject: format code --- .../android/native_app/lvgl_basic/src/main.c | 40 ++++++++--------- .../android/native_app/lvgl_particles/src/main.c | 52 +++++++++++----------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/tests/projects/android/native_app/lvgl_basic/src/main.c b/tests/projects/android/native_app/lvgl_basic/src/main.c index 56518a22a..9335f60ea 100644 --- a/tests/projects/android/native_app/lvgl_basic/src/main.c +++ b/tests/projects/android/native_app/lvgl_basic/src/main.c @@ -32,7 +32,7 @@ static void my_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * p int32_t width = lv_area_get_width(area); int32_t height = lv_area_get_height(area); - + // Assume 32-bit RGBA uint32_t * dst_base = (uint32_t *)buffer.bits; uint32_t * src = (uint32_t *)px_map; @@ -58,7 +58,7 @@ static void create_ui(void) { lv_label_set_text(label, "Hello Xmake + LVGL!"); lv_obj_set_style_text_font(label, &lv_font_montserrat_14, 0); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); - + // FPS label lv_obj_t * label_fps = lv_label_create(lv_screen_active()); lv_label_set_text(label_fps, "FPS: 0"); @@ -74,20 +74,20 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { window_width = ANativeWindow_getWidth(native_window); window_height = ANativeWindow_getHeight(native_window); ANativeWindow_setBuffersGeometry(native_window, window_width, window_height, WINDOW_FORMAT_RGBA_8888); - + if (!display) { display = lv_display_create(window_width, window_height); lv_display_set_color_format(display, LV_COLOR_FORMAT_ARGB8888); lv_display_set_flush_cb(display, my_flush_cb); - + size_t buf_size = window_width * window_height * 4; void * buf = malloc(buf_size); lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); - + lv_indev_t * indev = lv_indev_create(); lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); lv_indev_set_read_cb(indev, my_input_read); - + create_ui(); } else { lv_display_set_resolution(display, window_width, window_height); @@ -117,10 +117,10 @@ static int32_t handle_input(struct android_app* app, AInputEvent* event) { void android_main(struct android_app* app) { lv_init(); - + app->onAppCmd = handle_cmd; app->onInputEvent = handle_input; - + int frame_count = 0; time_t last_time = time(NULL); @@ -128,26 +128,26 @@ void android_main(struct android_app* app) { int ident; int events; struct android_poll_source* source; - + uint32_t timeout = lv_timer_handler(); if (timeout > 50) timeout = 50; - + while ((ident = ALooper_pollAll(timeout, NULL, &events, (void**)&source)) >= 0) { if (source != NULL) source->process(app, source); if (app->destroyRequested != 0) return; } - + lv_tick_inc(timeout); frame_count++; - time_t current_time = time(NULL); - if (current_time - last_time >= 1) { - lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps - if (label_fps) { - lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); - } - frame_count = 0; - last_time = current_time; - } + time_t current_time = time(NULL); + if (current_time - last_time >= 1) { + lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps + if (label_fps) { + lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); + } + frame_count = 0; + last_time = current_time; + } } } diff --git a/tests/projects/android/native_app/lvgl_particles/src/main.c b/tests/projects/android/native_app/lvgl_particles/src/main.c index 0d34298e4..915b0c116 100644 --- a/tests/projects/android/native_app/lvgl_particles/src/main.c +++ b/tests/projects/android/native_app/lvgl_particles/src/main.c @@ -32,7 +32,7 @@ static void my_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * p int32_t width = lv_area_get_width(area); int32_t height = lv_area_get_height(area); - + // Assume 32-bit RGBA uint32_t * dst_base = (uint32_t *)buffer.bits; uint32_t * src = (uint32_t *)px_map; @@ -88,7 +88,7 @@ static void update_particles(void) { p->x += p->vx; p->y += p->vy; p->life--; - + if (p->life <= 0 || p->x < 0 || p->x > window_width || p->y < 0 || p->y > window_height) { *p = particles[--particle_count]; i--; @@ -100,18 +100,18 @@ static void draw_particles(lv_layer_t * layer) { lv_draw_rect_dsc_t draw_dsc; lv_draw_rect_dsc_init(&draw_dsc); draw_dsc.radius = LV_RADIUS_CIRCLE; - + for (int i = 0; i < particle_count; i++) { Particle *p = &particles[i]; draw_dsc.bg_color = p->color; draw_dsc.bg_opa = (p->life * 255) / 100; - + lv_area_t area; area.x1 = p->x - p->size / 2; area.y1 = p->y - p->size / 2; area.x2 = area.x1 + p->size; area.y2 = area.y1 + p->size; - + lv_draw_rect(layer, &draw_dsc, &area); } } @@ -129,7 +129,7 @@ static void particle_timer_cb(lv_timer_t * timer) { int cy = window_height / 2 + sin(t) * (window_height / 4); create_particle(cx, cy); } - + update_particles(); lv_obj_invalidate(lv_scr_act()); // Force redraw } @@ -144,16 +144,16 @@ static void create_ui(void) { lv_label_set_text(label, "Touch to create particles!"); lv_obj_set_style_text_font(label, &lv_font_montserrat_14, 0); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); - + // FPS label lv_obj_t * label_fps = lv_label_create(lv_screen_active()); lv_label_set_text(label_fps, "FPS: 0"); lv_obj_set_style_text_font(label_fps, &lv_font_montserrat_14, 0); lv_obj_align(label_fps, LV_ALIGN_TOP_MID, 0, 100); - + // Add draw event to screen for particles lv_obj_add_event_cb(lv_screen_active(), canvas_draw_event_cb, LV_EVENT_DRAW_POST, NULL); - + lv_timer_create(particle_timer_cb, 16, NULL); } @@ -165,20 +165,20 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { window_width = ANativeWindow_getWidth(native_window); window_height = ANativeWindow_getHeight(native_window); ANativeWindow_setBuffersGeometry(native_window, window_width, window_height, WINDOW_FORMAT_RGBA_8888); - + if (!display) { display = lv_display_create(window_width, window_height); lv_display_set_color_format(display, LV_COLOR_FORMAT_ARGB8888); lv_display_set_flush_cb(display, my_flush_cb); - + size_t buf_size = window_width * window_height * 4; void * buf = malloc(buf_size); lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); - + lv_indev_t * indev = lv_indev_create(); lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); lv_indev_set_read_cb(indev, my_input_read); - + create_ui(); } else { lv_display_set_resolution(display, window_width, window_height); @@ -208,37 +208,37 @@ static int32_t handle_input(struct android_app* app, AInputEvent* event) { void android_main(struct android_app* app) { lv_init(); - + app->onAppCmd = handle_cmd; app->onInputEvent = handle_input; - + int frame_count = 0; time_t last_time = time(NULL); - + while (1) { int ident; int events; struct android_poll_source* source; - + uint32_t timeout = lv_timer_handler(); if (timeout > 50) timeout = 50; - + while ((ident = ALooper_pollAll(timeout, NULL, &events, (void**)&source)) >= 0) { if (source != NULL) source->process(app, source); if (app->destroyRequested != 0) return; } - + lv_tick_inc(timeout); - + frame_count++; time_t current_time = time(NULL); if (current_time - last_time >= 1) { - lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps - if (label_fps) { - lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); - } - frame_count = 0; - last_time = current_time; + lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps + if (label_fps) { + lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); + } + frame_count = 0; + last_time = current_time; } } } -- cgit v1.3.1 From cb4c88034ab1d4dc5dedb0dbe56f5e868cae0ecd Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:52:51 +0800 Subject: improve lvgl demo --- .../android/native_app/lvgl_basic/src/main.c | 26 +++++++++++++++++---- .../android/native_app/lvgl_particles/src/main.c | 27 ++++++++++++++++++---- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/tests/projects/android/native_app/lvgl_basic/src/main.c b/tests/projects/android/native_app/lvgl_basic/src/main.c index 9335f60ea..f07036e9b 100644 --- a/tests/projects/android/native_app/lvgl_basic/src/main.c +++ b/tests/projects/android/native_app/lvgl_basic/src/main.c @@ -10,9 +10,12 @@ #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) static lv_display_t * display = NULL; +static lv_indev_t * indev = NULL; +static void * disp_buf = NULL; static ANativeWindow * native_window = NULL; static int32_t window_width = 0; static int32_t window_height = 0; +static lv_obj_t * label_fps = NULL; static bool touch_down = false; static int32_t touch_x = 0; @@ -60,7 +63,7 @@ static void create_ui(void) { lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); // FPS label - lv_obj_t * label_fps = lv_label_create(lv_screen_active()); + label_fps = lv_label_create(lv_screen_active()); lv_label_set_text(label_fps, "FPS: 0"); lv_obj_set_style_text_font(label_fps, &lv_font_montserrat_14, 0); lv_obj_align(label_fps, LV_ALIGN_TOP_MID, 0, 100); @@ -81,10 +84,10 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { lv_display_set_flush_cb(display, my_flush_cb); size_t buf_size = window_width * window_height * 4; - void * buf = malloc(buf_size); - lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); + disp_buf = malloc(buf_size); + lv_display_set_buffers(display, disp_buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); - lv_indev_t * indev = lv_indev_create(); + indev = lv_indev_create(); lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); lv_indev_set_read_cb(indev, my_input_read); @@ -97,6 +100,20 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { case APP_CMD_TERM_WINDOW: native_window = NULL; break; + case APP_CMD_DESTROY: + if (display) { + lv_display_delete(display); + display = NULL; + } + if (indev) { + lv_indev_delete(indev); + indev = NULL; + } + if (disp_buf) { + free(disp_buf); + disp_buf = NULL; + } + break; } } @@ -142,7 +159,6 @@ void android_main(struct android_app* app) { frame_count++; time_t current_time = time(NULL); if (current_time - last_time >= 1) { - lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps if (label_fps) { lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); } diff --git a/tests/projects/android/native_app/lvgl_particles/src/main.c b/tests/projects/android/native_app/lvgl_particles/src/main.c index 915b0c116..1db849fc1 100644 --- a/tests/projects/android/native_app/lvgl_particles/src/main.c +++ b/tests/projects/android/native_app/lvgl_particles/src/main.c @@ -10,9 +10,12 @@ #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) static lv_display_t * display = NULL; +static lv_indev_t * indev = NULL; +static void * disp_buf = NULL; static ANativeWindow * native_window = NULL; static int32_t window_width = 0; static int32_t window_height = 0; +static lv_obj_t * label_fps = NULL; static bool touch_down = false; static int32_t touch_x = 0; @@ -146,7 +149,7 @@ static void create_ui(void) { lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 50); // FPS label - lv_obj_t * label_fps = lv_label_create(lv_screen_active()); + label_fps = lv_label_create(lv_screen_active()); lv_label_set_text(label_fps, "FPS: 0"); lv_obj_set_style_text_font(label_fps, &lv_font_montserrat_14, 0); lv_obj_align(label_fps, LV_ALIGN_TOP_MID, 0, 100); @@ -172,10 +175,10 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { lv_display_set_flush_cb(display, my_flush_cb); size_t buf_size = window_width * window_height * 4; - void * buf = malloc(buf_size); - lv_display_set_buffers(display, buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); + disp_buf = malloc(buf_size); + lv_display_set_buffers(display, disp_buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_FULL); - lv_indev_t * indev = lv_indev_create(); + indev = lv_indev_create(); lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); lv_indev_set_read_cb(indev, my_input_read); @@ -188,6 +191,20 @@ static void handle_cmd(struct android_app* app, int32_t cmd) { case APP_CMD_TERM_WINDOW: native_window = NULL; break; + case APP_CMD_DESTROY: + if (display) { + lv_display_delete(display); + display = NULL; + } + if (indev) { + lv_indev_delete(indev); + indev = NULL; + } + if (disp_buf) { + free(disp_buf); + disp_buf = NULL; + } + break; } } @@ -207,6 +224,7 @@ static int32_t handle_input(struct android_app* app, AInputEvent* event) { } void android_main(struct android_app* app) { + srand(time(NULL)); lv_init(); app->onAppCmd = handle_cmd; @@ -233,7 +251,6 @@ void android_main(struct android_app* app) { frame_count++; time_t current_time = time(NULL); if (current_time - last_time >= 1) { - lv_obj_t * label_fps = lv_obj_get_child(lv_screen_active(), 1); // 0: label, 1: fps if (label_fps) { lv_label_set_text_fmt(label_fps, "FPS: %d", frame_count); } -- cgit v1.3.1 From 7b542ebe22e833bd56dd1eb0271aa5aa7c0b45a8 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Dec 2025 23:56:05 +0800 Subject: move ndk rules to android --- xmake/rules/ndk/install.lua | 34 ---------- xmake/rules/ndk/load.lua | 44 ------------ xmake/rules/ndk/package.lua | 103 ----------------------------- xmake/rules/ndk/run.lua | 56 ---------------- xmake/rules/ndk/uninstall.lua | 32 --------- xmake/rules/ndk/xmake.lua | 53 --------------- xmake/rules/platform/android/install.lua | 34 ++++++++++ xmake/rules/platform/android/load.lua | 44 ++++++++++++ xmake/rules/platform/android/package.lua | 103 +++++++++++++++++++++++++++++ xmake/rules/platform/android/run.lua | 56 ++++++++++++++++ xmake/rules/platform/android/uninstall.lua | 32 +++++++++ xmake/rules/platform/android/xmake.lua | 53 +++++++++++++++ 12 files changed, 322 insertions(+), 322 deletions(-) delete mode 100644 xmake/rules/ndk/install.lua delete mode 100644 xmake/rules/ndk/load.lua delete mode 100644 xmake/rules/ndk/package.lua delete mode 100644 xmake/rules/ndk/run.lua delete mode 100644 xmake/rules/ndk/uninstall.lua delete mode 100644 xmake/rules/ndk/xmake.lua create mode 100644 xmake/rules/platform/android/install.lua create mode 100644 xmake/rules/platform/android/load.lua create mode 100644 xmake/rules/platform/android/package.lua create mode 100644 xmake/rules/platform/android/run.lua create mode 100644 xmake/rules/platform/android/uninstall.lua create mode 100644 xmake/rules/platform/android/xmake.lua diff --git a/xmake/rules/ndk/install.lua b/xmake/rules/ndk/install.lua deleted file mode 100644 index ec340ac00..000000000 --- a/xmake/rules/ndk/install.lua +++ /dev/null @@ -1,34 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author keosu --- @file install.lua --- - --- imports - -function main(target) - - local android_sdkdir = target:toolchain("ndk"):config("android_sdk") - local adb = path.join(android_sdkdir, "platform-tools", "adb") - - local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - assert(os.isfile(final_apk), "apk file %s not found!", final_apk) - - cprint("installing %s ...", final_apk) - os.vrunv(adb, {"install", "-r", final_apk}) - cprint("install ok") -end diff --git a/xmake/rules/ndk/load.lua b/xmake/rules/ndk/load.lua deleted file mode 100644 index 3e49d9533..000000000 --- a/xmake/rules/ndk/load.lua +++ /dev/null @@ -1,44 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author keosu --- @file load.lua --- - -function main(target) - - -- only for android target - if not target:is_plat("android") then - wprint("rule(android.native_app): only for android system!") - target:rule_enable("android.native_app", false) - return - end - - local toolchain_ndk = target:toolchain("ndk") - local ndk_root = toolchain_ndk:config("ndk") - if not ndk_root then - raise("NDK path not set! Please set NDK path properly.") - end - - -- set target kind - target:set("kind", "shared") - - -- add glue file to target - local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") - local native_app_glue_dir = path.directory(native_app_glue_file) - target:add("files", native_app_glue_file) - target:add("includedirs", native_app_glue_dir) -end diff --git a/xmake/rules/ndk/package.lua b/xmake/rules/ndk/package.lua deleted file mode 100644 index 00142a85f..000000000 --- a/xmake/rules/ndk/package.lua +++ /dev/null @@ -1,103 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author keosu --- @file package.lua --- - --- imports -import("core.project.depend") -import("utils.progress") - -function main(target, opt) - - local conf = target:extraconf("rules", "android.native_app") - local android_sdk_version = conf.android_sdk_version - local android_manifest = conf.android_manifest - local android_res = conf.android_res - local android_assets = conf.android_assets - local keystore = conf.keystore - local keystore_pass = conf.keystore_pass - - assert(android_sdk_version, "android sdk version not set") - assert(android_manifest, "android manifest not set") - - local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") - - -- add dependencies - local depfiles = {target:targetfile(), android_manifest, keystore} - if android_res and os.isdir(android_res) then - table.join2(depfiles, os.files(path.join(android_res, "**"))) - end - if android_assets and os.isdir(android_assets) then - table.join2(depfiles, os.files(path.join(android_assets, "**"))) - end - - depend.on_changed(function () - progress.show(opt.progress, "${color.build.target}packing.apk %s", final_apk) - - local tmp_path = path.join(target:targetdir(), "temp") - os.mkdir(tmp_path) - os.mkdir(path.join(tmp_path, "lib")) - os.mkdir(path.join(tmp_path, "lib", target:arch())) - - -- copy the target library to temp folder with name libmain.so - local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") - os.cp(target:targetfile(), libfile) - - -- get android tool path - local android_sdkdir = target:toolchain("ndk"):config("android_sdk") - local android_build_toolver = target:toolchain("ndk"):config("build_toolver") - local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) - - local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) - local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) - local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) - - -- pack resources - local resonly_apk = path.join(tmp_path, "res_only.apk") - local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), - "android.jar") - assert(os.isfile(androidjar), "%s not found", androidjar) - local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} - - if android_res and not os.emptydir(android_res) then - table.insert(aapt_argv, "-S") - table.insert(aapt_argv, android_res) - end - - if android_assets and not os.emptydir(android_assets) then - table.insert(aapt_argv, "-A") - table.insert(aapt_argv, android_assets) - end - - os.vrunv(aapt, aapt_argv) - - -- pack libs - os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) - - -- align apk - local aligned_apk = path.join(tmp_path, "unsigned.apk") - local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} - - os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) - - -- sign apk - local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", - final_apk, "--in", aligned_apk} - os.vrunv(apksigner, apksigner_argv) - end, {dependfile = target:dependfile(final_apk), files = depfiles, values = {android_sdk_version, keystore_pass}}) -end diff --git a/xmake/rules/ndk/run.lua b/xmake/rules/ndk/run.lua deleted file mode 100644 index 657dad4e8..000000000 --- a/xmake/rules/ndk/run.lua +++ /dev/null @@ -1,56 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author keosu --- @file run.lua --- - --- imports -import("core.base.tty") -import("install", {alias = "install_app"}) - -function main(target) - - -- install it first - install_app(target) - - local conf = target:extraconf("rules", "android.native_app") - local package_name = conf.package_name - local activity_name = conf.activity_name or "android.app.NativeActivity" - - local android_sdkdir = target:toolchain("ndk"):config("android_sdk") - local adb = path.join(android_sdkdir, "platform-tools", "adb") - - local run_argv = {"shell", "am", "start", "-n", package_name .. "/" .. activity_name} - - cprint("running %s ...", package_name) - os.vrunv(adb, run_argv) - - -- show logcat - local logcat_argv = {"logcat"} - if io.isatty() and (tty.has_color8() or tty.has_color256()) then - table.insert(logcat_argv, "-v") - table.insert(logcat_argv, "color") - end - local logcat_filters = conf.logcat_filters - if logcat_filters then - table.insert(logcat_argv, "-s") - for _, filter in ipairs(logcat_filters) do - table.insert(logcat_argv, filter) - end - end - os.execv(adb, logcat_argv) -end diff --git a/xmake/rules/ndk/uninstall.lua b/xmake/rules/ndk/uninstall.lua deleted file mode 100644 index 24564d631..000000000 --- a/xmake/rules/ndk/uninstall.lua +++ /dev/null @@ -1,32 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author ruki --- @file uninstall.lua --- - -function main(target) - - local conf = target:extraconf("rules", "android.native_app") - local package_name = conf.package_name - - local android_sdkdir = target:toolchain("ndk"):config("android_sdk") - local adb = path.join(android_sdkdir, "platform-tools", "adb") - - cprint("uninstalling %s ...", package_name) - os.vrunv(adb, {"uninstall", package_name}) - cprint("uninstall ok") -end diff --git a/xmake/rules/ndk/xmake.lua b/xmake/rules/ndk/xmake.lua deleted file mode 100644 index 0c58d7d09..000000000 --- a/xmake/rules/ndk/xmake.lua +++ /dev/null @@ -1,53 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015-present, Xmake Open Source Community. --- --- @author keosu --- @file xmake.lua --- - --- define rule: build android native app with NDK --- --- @code --- target("test") --- set_kind("binary") --- add_rules("android.native_app", { --- android_sdk_version = "35", --- android_manifest = "android/AndroidManifest.xml", --- android_res = "android/res", --- android_assets = "android/assets", --- keystore = "android/debug.jks", --- keystore_pass = "123456", --- package_name = "com.raylib.demo", --- logcat_filters = {"raydemo_android", "raylib"} --- }) --- @endcode --- -rule("android.native_app") - - -- we must set_kind and add some glue files to target - on_load("load") - - -- generate android apk package - after_build("package") - - -- install android package with adb - on_install("install") - - -- uninstall android package with adb - on_uninstall("uninstall") - - -- run android app through adb - on_run("run") diff --git a/xmake/rules/platform/android/install.lua b/xmake/rules/platform/android/install.lua new file mode 100644 index 000000000..ec340ac00 --- /dev/null +++ b/xmake/rules/platform/android/install.lua @@ -0,0 +1,34 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file install.lua +-- + +-- imports + +function main(target) + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") + assert(os.isfile(final_apk), "apk file %s not found!", final_apk) + + cprint("installing %s ...", final_apk) + os.vrunv(adb, {"install", "-r", final_apk}) + cprint("install ok") +end diff --git a/xmake/rules/platform/android/load.lua b/xmake/rules/platform/android/load.lua new file mode 100644 index 000000000..3e49d9533 --- /dev/null +++ b/xmake/rules/platform/android/load.lua @@ -0,0 +1,44 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file load.lua +-- + +function main(target) + + -- only for android target + if not target:is_plat("android") then + wprint("rule(android.native_app): only for android system!") + target:rule_enable("android.native_app", false) + return + end + + local toolchain_ndk = target:toolchain("ndk") + local ndk_root = toolchain_ndk:config("ndk") + if not ndk_root then + raise("NDK path not set! Please set NDK path properly.") + end + + -- set target kind + target:set("kind", "shared") + + -- add glue file to target + local native_app_glue_file = path.join(ndk_root, "sources", "android", "native_app_glue", "android_native_app_glue.c") + local native_app_glue_dir = path.directory(native_app_glue_file) + target:add("files", native_app_glue_file) + target:add("includedirs", native_app_glue_dir) +end diff --git a/xmake/rules/platform/android/package.lua b/xmake/rules/platform/android/package.lua new file mode 100644 index 000000000..00142a85f --- /dev/null +++ b/xmake/rules/platform/android/package.lua @@ -0,0 +1,103 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file package.lua +-- + +-- imports +import("core.project.depend") +import("utils.progress") + +function main(target, opt) + + local conf = target:extraconf("rules", "android.native_app") + local android_sdk_version = conf.android_sdk_version + local android_manifest = conf.android_manifest + local android_res = conf.android_res + local android_assets = conf.android_assets + local keystore = conf.keystore + local keystore_pass = conf.keystore_pass + + assert(android_sdk_version, "android sdk version not set") + assert(android_manifest, "android manifest not set") + + local final_apk = path.join(target:targetdir(), target:basename() .. ".apk") + + -- add dependencies + local depfiles = {target:targetfile(), android_manifest, keystore} + if android_res and os.isdir(android_res) then + table.join2(depfiles, os.files(path.join(android_res, "**"))) + end + if android_assets and os.isdir(android_assets) then + table.join2(depfiles, os.files(path.join(android_assets, "**"))) + end + + depend.on_changed(function () + progress.show(opt.progress, "${color.build.target}packing.apk %s", final_apk) + + local tmp_path = path.join(target:targetdir(), "temp") + os.mkdir(tmp_path) + os.mkdir(path.join(tmp_path, "lib")) + os.mkdir(path.join(tmp_path, "lib", target:arch())) + + -- copy the target library to temp folder with name libmain.so + local libfile = path.join(tmp_path, "lib", target:arch(), "libmain.so") + os.cp(target:targetfile(), libfile) + + -- get android tool path + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local android_build_toolver = target:toolchain("ndk"):config("build_toolver") + local sdk_tool_path = path.join(android_sdkdir, "build-tools", android_build_toolver) + + local aapt = path.join(sdk_tool_path, "aapt" .. (is_host("windows") and ".exe" or "")) + local zipalign = path.join(sdk_tool_path, "zipalign" .. (is_host("windows") and ".exe" or "")) + local apksigner = path.join(sdk_tool_path, "apksigner" .. (is_host("windows") and ".bat" or "")) + + -- pack resources + local resonly_apk = path.join(tmp_path, "res_only.apk") + local androidjar = path.join(android_sdkdir, "platforms", string.format("android-%s", android_sdk_version), + "android.jar") + assert(os.isfile(androidjar), "%s not found", androidjar) + local aapt_argv = {"package", "-f", "-M", android_manifest, "-I", androidjar, "-F", resonly_apk} + + if android_res and not os.emptydir(android_res) then + table.insert(aapt_argv, "-S") + table.insert(aapt_argv, android_res) + end + + if android_assets and not os.emptydir(android_assets) then + table.insert(aapt_argv, "-A") + table.insert(aapt_argv, android_assets) + end + + os.vrunv(aapt, aapt_argv) + + -- pack libs + os.vrunv(aapt, {"add", "res_only.apk", "lib/" .. target:arch() .."/libmain.so"}, {curdir = tmp_path}) + + -- align apk + local aligned_apk = path.join(tmp_path, "unsigned.apk") + local zipalign_argv = {"-f", "4", "res_only.apk", "unsigned.apk"} + + os.vrunv(zipalign, zipalign_argv, {curdir = tmp_path}) + + -- sign apk + local apksigner_argv = {"sign", "--ks", keystore, "--ks-pass", string.format("pass:%s", keystore_pass), "--out", + final_apk, "--in", aligned_apk} + os.vrunv(apksigner, apksigner_argv) + end, {dependfile = target:dependfile(final_apk), files = depfiles, values = {android_sdk_version, keystore_pass}}) +end diff --git a/xmake/rules/platform/android/run.lua b/xmake/rules/platform/android/run.lua new file mode 100644 index 000000000..657dad4e8 --- /dev/null +++ b/xmake/rules/platform/android/run.lua @@ -0,0 +1,56 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file run.lua +-- + +-- imports +import("core.base.tty") +import("install", {alias = "install_app"}) + +function main(target) + + -- install it first + install_app(target) + + local conf = target:extraconf("rules", "android.native_app") + local package_name = conf.package_name + local activity_name = conf.activity_name or "android.app.NativeActivity" + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + local run_argv = {"shell", "am", "start", "-n", package_name .. "/" .. activity_name} + + cprint("running %s ...", package_name) + os.vrunv(adb, run_argv) + + -- show logcat + local logcat_argv = {"logcat"} + if io.isatty() and (tty.has_color8() or tty.has_color256()) then + table.insert(logcat_argv, "-v") + table.insert(logcat_argv, "color") + end + local logcat_filters = conf.logcat_filters + if logcat_filters then + table.insert(logcat_argv, "-s") + for _, filter in ipairs(logcat_filters) do + table.insert(logcat_argv, filter) + end + end + os.execv(adb, logcat_argv) +end diff --git a/xmake/rules/platform/android/uninstall.lua b/xmake/rules/platform/android/uninstall.lua new file mode 100644 index 000000000..24564d631 --- /dev/null +++ b/xmake/rules/platform/android/uninstall.lua @@ -0,0 +1,32 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author ruki +-- @file uninstall.lua +-- + +function main(target) + + local conf = target:extraconf("rules", "android.native_app") + local package_name = conf.package_name + + local android_sdkdir = target:toolchain("ndk"):config("android_sdk") + local adb = path.join(android_sdkdir, "platform-tools", "adb") + + cprint("uninstalling %s ...", package_name) + os.vrunv(adb, {"uninstall", package_name}) + cprint("uninstall ok") +end diff --git a/xmake/rules/platform/android/xmake.lua b/xmake/rules/platform/android/xmake.lua new file mode 100644 index 000000000..0c58d7d09 --- /dev/null +++ b/xmake/rules/platform/android/xmake.lua @@ -0,0 +1,53 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author keosu +-- @file xmake.lua +-- + +-- define rule: build android native app with NDK +-- +-- @code +-- target("test") +-- set_kind("binary") +-- add_rules("android.native_app", { +-- android_sdk_version = "35", +-- android_manifest = "android/AndroidManifest.xml", +-- android_res = "android/res", +-- android_assets = "android/assets", +-- keystore = "android/debug.jks", +-- keystore_pass = "123456", +-- package_name = "com.raylib.demo", +-- logcat_filters = {"raydemo_android", "raylib"} +-- }) +-- @endcode +-- +rule("android.native_app") + + -- we must set_kind and add some glue files to target + on_load("load") + + -- generate android apk package + after_build("package") + + -- install android package with adb + on_install("install") + + -- uninstall android package with adb + on_uninstall("uninstall") + + -- run android app through adb + on_run("run") -- cgit v1.3.1