Skip to content

Conversation

@keosu
Copy link
Contributor

@keosu keosu commented Dec 11, 2025

  • on_load: Add glue file to target and set_kind to shared library
  • on_package: Generate android apk package
  • on_install: install the app with adb
  • on_run: run the app with adb (have trouble to overwrite on_run, use after_install for workaround now)

Test project path: https://github.com/keosu/xmake/tree/dev/tests/projects/c%2B%2B/ndk_raylib

A standalone example repo: https://github.com/keosu/raycpp_android_xmake/tree/pr Andriod CI pass

    - Add glue file and jni interface file to target;
    - Generate android apk package at install stage;
    - Use adb to run the android app.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @keosu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances xmake's capabilities for Android C++ development by introducing a dedicated rule that automates the entire build, packaging, and deployment lifecycle. It integrates seamlessly with the Android SDK and NDK toolchains, abstracting away the complexities of APK creation, signing, and on-device execution, thereby providing a more efficient and developer-friendly experience.

Highlights

  • New Android C++ Rule: Introduces a new android.cpp rule within xmake, specifically designed to streamline the build process for Android C++ projects.
  • Automated APK Generation: Adds functionality to automatically package resources, native libraries, align, and sign Android APKs using aapt, zipalign, and apksigner.
  • ADB Integration for Running Apps: Enables direct installation and launching of Android applications on a connected device through adb, simplifying the testing workflow.
  • JNI and Native Glue Support: Automatically includes the android_native_app_glue.c from the NDK and allows for the specification of a JNI interface file, facilitating native code integration.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new xmake rule for building Android C++ applications, which includes functionality for packaging an APK and running it on a device. My review has identified a few areas for improvement to enhance the robustness, security, and correctness of the new rule. Key feedback includes fixing a critical bug related to a hardcoded architecture, addressing a security concern with a default keystore password, improving error handling, and correcting some typos and dead code. The suggested changes aim to make the new rule more reliable and secure for users.

@waruqi
Copy link
Member

waruqi commented Dec 12, 2025

你这里的用法是作为 android native app 来构建的。

那 install 的逻辑就不对,不应该是 打包 apk 而应该是 直接安装到设备。

  1. xmake build: 构建生成 .apk 包括完成签名
  2. xmake install: 将 apk 安装到设备
  3. xmake run 在设备上运行安装后的 app

@waruqi
Copy link
Member

waruqi commented Dec 12, 2025

另外,你现在的测试工程,这边签名有问题

ruki:raycpp_android_xmake ruki$ xmake install -o build cppray
installing cppray ..
installing cppray to build ..
[Android][Packing resources] Save to build/android/output/temp/res_only.apk...
[Android][Packing library] Adding lib/arm64-v8a/libmain.so to res_only.apk...
[Android][Align apk] Save to build/android/output/temp/unsigned.apk...
[Android][Signing apk] Save to build/cppray.apk...
error: install failed, Failed to load signer "signer #1"
java.io.IOException: Invalid keystore format
	at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:663)
	at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
	at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
	at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
	at java.security.KeyStore.load(KeyStore.java:1445)
	at com.android.apksigner.SignerParams.loadKeyStoreFromFile(SignerParams.java:423)
	at com.android.apksigner.SignerParams.loadPrivateKeyAndCertsFromKeyStore(SignerParams.java:309)
	at com.android.apksigner.SignerParams.loadPrivateKeyAndCerts(SignerParams.java:237)
	at com.android.apksigner.ApkSignerTool.getSignerConfig(ApkSignerTool.java:449)
	at com.android.apksigner.ApkSignerTool.sign(ApkSignerTool.java:362)
	at com.android.apksigner.ApkSignerTool.main(ApkSignerTool.java:94)

@waruqi
Copy link
Member

waruqi commented Dec 12, 2025

还有,请在 tests 下提供一个完整的测试例子工程,不要有中文注释,不要有无关的东西,尽可能最精简的模版工程。

还有 rule 定义开头,加上完整的使用注释

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Also, please provide a complete test example project under tests. No Chinese comments, no irrelevant things, and the most streamlined template project possible.

There is also the beginning of the rule definition, plus complete usage comments

@keosu keosu changed the title Add rule for android c++ Add rule for android native app Dec 12, 2025
@keosu keosu changed the title Add rule for android native app Add rule for android native app(NDK) Dec 12, 2025
@keosu
Copy link
Contributor Author

keosu commented Dec 12, 2025

Hi @waruqi , thanks for your review, I have updated the PR and resolved most issues, please help to review again.
In this update, I have problem to overwrite the on_run action(I use after_install for a workaround), any suggestion for this?
And I didn't have the signing issue as you mentioned, I have tested this with local machine and the github action. Are you using a macbook, or have you tried to use a keystore file genereated by youself?

-- define rule: build android native app with NDK
rule("android.native_app")
-- this rule only for android target
if is_plat("android") then
Copy link
Member

Choose a reason for hiding this comment

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

Did you test it? please call target:is_plat in script scope.

error: @programdir/rules/ndk/xmake.lua:24: attempt to call a nil value (global 'is_plat')
stack traceback:
    [@programdir/rules/ndk/xmake.lua:24]: in main chunk

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's weird, is_plat works well on my windows laptop and the ubuntu ci while target:is_plat not.
But this is tested as an external custom rule, does this matter? I don't know how to test within xmake project itself now, and the CI seems not triggered for my PR.

Copy link
Member

Choose a reason for hiding this comment

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

you need to add a test.lua file in example project folder. you can see other tests example

Copy link
Member

Choose a reason for hiding this comment

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

but there is not android ndk on ci now, maybe it cannot be tested.

@waruqi waruqi mentioned this pull request Dec 16, 2025
2 tasks
@waruqi
Copy link
Member

waruqi commented Dec 16, 2025

Because there were too many changes required, I made some improvements based on your patch: #7139

@waruqi waruqi closed this Dec 16, 2025
@waruqi
Copy link
Member

waruqi commented Dec 16, 2025

#7141

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants