Naylib Goes Mobile: Porting to Android in Just 3 Days!


Hello there! In this post, I'll share how I managed to port my Nim raylib bindings to Android in just three days. I'll talk about the challenges I faced and the solutions I used to make it happen. To be honest, I had no clue about Android development before starting this project. I just wanted to show off my cool demos to my classmates on my phone. So, after my exams were over and I had a few free days, I got right into it.

Background

So, I had recently revamped my build system. I dumped the outdated nake tool and started using nimble tasks instead. I also took into account some feedback from users of my library who weren't too happy. I changed the way the raylib static library is built by using this cool compile pragma that builds the C sources alongside the nim project. This approach makes it easier to target different platforms. So, let's say I want to develop a web game now, all I have to do is provide the right --cpu and --os command arguments when building my project.

Day 1

My main focus on the first day was getting one of the official raylib examples to work on Android. This would allow me to compare it with my implementation and make sure everything was working as expected. Fortunately, Ray had already put in a lot of effort to support Android in his library. He provided helpful wiki pages on how to generate APK files, which I followed to install the Android SDK and NDK. I also found a template project with a makefile for Android and a community-led project with a bash-based build system.

Unfortunately, the Android support was outdated, and the makefile provided only worked on Windows. I tried using the bash script to generate an APK, but it didn't work with recent Android versions and failed to install properly. I also couldn't figure why it kept crashing when switching to the arm64 architecture. So, I decided to port the makefile to Linux, which was a bit of a bumpy ride. Creating a multi-platform makefile was a real challenge, and I didn't want to spend another day on it.

Day 2

Feeling frustrated with the previous day's failures, I decided to go all-in and just convert the Makefile.Android to Nimscript. Surprisingly, it went pretty smoothly since I had spent the previous day learning how it worked and using ChatGPT as my secret weapon. I was able to translate most of it before noon with just a few prompts, and ChatGPT did a decent job considering it had little training in the Nim language. Its main struggle was remembering to use the correct functions from the Nim standard library and not confusing it with Python.

Once I had the code that creates and populates the project's build directory working, it was time to extract the compile and link commands for Nim from the Makefile. This involved creating a when defined(android) block and pasting the parameters to passC/passL commands. I was almost there, but the next step was to set the correct cross-compiler.

I found the hostCPU constant a bit confusing because it emulated the target CPU, which is affected by the --cpu switch. However, after reading the Android docs, I was able to direct my config to the right compiler provided by the Android NDK.

Day 3

The pressure was on for the next day but I was almost done, I may had being able to produce non working APKs already from day 2 but I wouldn't stop till I had a working one.

Where I stumbled a lot of my time was the ages-ago deprecation of the dx bytecode compiler and removal from the Android SDK. And figuring out the appropriate migration path to d8. After debugging with adb logcat a silly mistake that prevented the shared library from being loaded, I had my first project running on Android.


The remaining time of the day was spent cleaning up my project and taking some much-needed rest. In the following days, I added multi-target APK support, although I heard that it might not be appropriate for publishing apps on the Play Store. This was superseded by App Bundles.

Conclusion

Overall, it was a valuable experience that I'm happy to share. Not only did it make my library ready for Android, but I also contributed my fixes upstream to raylib. You can learn more about how to take advantage of my work on the Nim blog.
 

Comments

Popular posts from this blog

Using NimScript for your build system

An introduction to ECS by example