summaryrefslogtreecommitdiff
path: root/xmake
diff options
context:
space:
mode:
authorYi Jianlong <[email protected]>2025-12-12 15:00:44 +0800
committerYi Jianlong <[email protected]>2025-12-13 00:45:05 +0800
commit7298699afb4e2baf50978cda9b2cc8822170301b (patch)
tree0d467fb4fa2b17d2b4c956ec2b4144c544b0d0e1 /xmake
parent711feadb87c1224de4fa81745d7a13565aeda10d (diff)
refactor the android native app rule and add a simple test project
Diffstat (limited to 'xmake')
-rw-r--r--xmake/rules/android/android_install.lua91
-rw-r--r--xmake/rules/android/android_run.lua31
-rw-r--r--xmake/rules/android/xmake.lua53
-rw-r--r--xmake/rules/ndk/install.lua34
-rw-r--r--xmake/rules/ndk/load.lua42
-rw-r--r--xmake/rules/ndk/package.lua97
-rw-r--r--xmake/rules/ndk/run.lua35
-rw-r--r--xmake/rules/ndk/xmake.lua33
8 files changed, 241 insertions, 175 deletions
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