YasuakiHonda / Maxima-on-Android-AS

Maxima on Android imported to Android Studio
23 stars 13 forks source link

How did you cross compile Maxima? #9

Open pouar opened 4 years ago

pouar commented 4 years ago

I'm trying to figure out how to update the Maxima binaries to the latest version, but I have no idea how you cross compiled Maxima for Android. The instructions on https://sites.google.com/site/maximaonandroid/home/how-to-build-maxima-on-android seem to be outdated, as there seems to be no crosscmp.lsp involved when cross compiling ECL anymore.

YasuakiHonda commented 4 years ago

Oh, good question. That site you refer to is not updated for many years.

Still, the basic idea is the same. 1) Cross compile ECL for Android is the first and most important step. 2) Compiling Maxima as dynamic object (library) or a module is very difficult, so I would suggest you forget about that. 3) It is easier to include all maxima source lisp files as if they were part of ECL. You may need to do adjustment here and there, such as file name collision between ECL and maxima. 4) I always chosen to compile everything in a static linked executable. 5) Don't forget about PIC and PIE treatment. That is mandatory since after Android 5 or 6.

Did you already succeed cross compiling ECL by yourself?

Thanks and best regards, Yasuaki Honda, Chiba, Japan

pouar commented 4 years ago

cross compiling ECL was pretty easy, so yes

pouar commented 4 years ago

by "include all maxima source lisp files as if they were part of ECL". You mean merge Maxima into the ECL source tree?

pouar commented 4 years ago

Or do you mean statically linking it with ECL?

pouar commented 4 years ago

Ok, I managed to figure out out to cross compile Maxima as a module using ASDF based off of the examples from EQL5-Android, but it involved patching ECL, as maxima::make-unspecial uses ffi::c-inline which doesn't work with the byte compiler, which is apparently needed to evaluate the Maxima code before cross compiling it.

pouar commented 4 years ago

these were the patches I used ecl.patch.gz maxima.patch.gz

pouar commented 4 years ago

also, I used the develop branch of ECL instead of 16.1.3, which I heard works with newer NDK

pouar commented 4 years ago

I picked the develop branch because that's what EQL5 did

pouar commented 4 years ago

also I had to set the logical host "SYS:**;*.*" to the path where the modules are on the android side as I haven't figured out how to do that from the cross compile environment yet.

pouar commented 4 years ago

changed maxima.patch a bit. maxima.patch.gz to compile Maxima, after setting up the cross compile environment mentioned in the ECL manual, you'd set the environmental variable TOOLCHAIN_PATH to the one mentioned in the ECL manual when cross compiling ECL for Android and set ECL_ANDROID to the prefix you installed the Android binary to. then cd to the Maxima directory, then run ./configure --enable-ecl --host=arm-linux-android then ${ECL_TO_RUN} --shell make.lisp. Which will build both a static library and a cross compiled fasl which can be loaded as a module

pouar commented 4 years ago

So far, I've only tested this resulting binary in Termux, haven't got it to work in the Android app yet. But this is how far I got so far.

YasuakiHonda commented 4 years ago

Wow, this is great. Congratulations!!

I do have couple of questions:

BTW, someone on the ecl-devel mailing list says the development branch is going to become ECL 20 soon and it is already in final testing phase. So picking it rather than 16.1.3 should be a good choice.

pouar commented 4 years ago

I used Arch Linux as the host, I used 19c for the ndk, I made a 32bit binary just so I could test it in Termux. Didn't have much trouble compiling bdwgc, but enabling generational garbage collection caused it to segfault. I didn't really run into any file name collision because I ended up compiling ECL and Maxima separately but statically linked them together using libmaxima.a, which is done by make.lisp that I put in the Maxima directory, although for some reason, the script sometimes complains about not being able to delete a fasc file that doesn't exist (no idea why it's doing that) but I managed to workaround that by using (si:install-bytecodes-compiler) then (asdf:load-system :maxima) before running make.lisp.

pouar commented 4 years ago

Did you make any changes to Maxima or ECL before packaging it for the Android app? As I didn't make any changes to it other than getting it to run in Termux.

pouar commented 4 years ago

btw, make.lisp is based on the examples EQL5-Android gave

pouar commented 4 years ago

Specifically, it is based on this script here https://gitlab.com/eql/EQL5-Android/-/blob/master/examples/REPL/make.lisp It was the easiest way to get it to cross compile for Android that I could think of. I suspect that the method for cross compiling ECL and Common Lisp applications for Android has changed a bit since you ported Maxima to Android, which would explain why you had trouble creating a fasl file for it, since that method didn't exist yet.

YasuakiHonda commented 4 years ago

Hi, I have a bit of time due to COVID19 and stay at home, and started working on compiling the latest Maxima (5.43.3) in the latest ECL (20.4.24). I will study what you have written so far above to reproduce your result.

Thanks for your valuable information!!

YasuakiHonda commented 4 years ago

I have successfully compiled Maxima-5.43.2 on ECL 20.4.24 using Android NDK r21 on Debian Linux 10 as a shared object (dynamic library).

I have created a Gist to share how to do this as step by step instructions. How to cross compile Maxima for Android

pouar commented 4 years ago

I keep getting this when I try to run your build

$ maxima/bin/rmaxima
rlwrap: warning: On this system rlwrap cannot follow the rlwrapped command's working directory:
filename completion will only be relative to rlwrap's own working directory

warnings can be silenced by the --no-warnings (-n) option

Condition of type: SIMPLE-PROGRAM-ERROR
Wrong number of arguments passed to function #<compiled-function EXT:FUNCTION-LAMBDA-LIST 0xb40dfc60>.
No restarts available.

Top level in: #<process TOP-LEVEL 0xb3e6ffc0>.
>
pouar commented 4 years ago

At least when trying to run it in Termux. I'm not sure what changes I need to make to the files in this repo to create the apk. I tried simply zipping the new binaries of the resulting Maxima up, but that didn't seem to work

pouar commented 4 years ago

ok, seems to be from trying to use NDK r21. NDK 19c works though

YasuakiHonda commented 4 years ago

Did you make the maxima binary work in either Termux or adb shell?

One important diffs of this maxima binary from past one is that this one is dynamic link while past binaries were static linked. As such, just replacing a single binary file were sufficient to make things work. In this situation, other shared object such as libecl.so needs to be installed in the directory and also LD_LIBRARY_PATH environment variable needs to be correctly set up. I would believe the following is a way to try:

/data/data/jp.yhonda/files/maxima to be a shell script setting up LD_LIBRARY_PATH and then call the actual binary somewhere in the additions directory.

pouar commented 4 years ago

I managed to get it to work in Termux after using NDK 19c and setting (logical-pathname-translations "SYS") to where ECL keeps its fasls it requires

pouar commented 4 years ago

Is there any way to get Android apps to give terminal output? I'm used to the environment giving me more detailed error messages.

pouar commented 4 years ago

ok, how do you update the version number for the apk? because I sorta got it working, but it seems to think it's the older version

pouar commented 4 years ago

I tried greping the repo for 5\.41\.0 but couldn't find anything

pouar commented 4 years ago

ok, just found out it's getting the startup message from maxima_svg.html, not maxima itself

pouar commented 4 years ago

ok, apparently it was stored as 3 separate integers, which is why grep didn't work

pouar commented 4 years ago

tbh, it was a lot easier for me to figure out how to develop for Termux than for regular Android, and I'm kinda stuck.

pouar commented 4 years ago

Can you even run a shell script like a regular executable in Android?

YasuakiHonda commented 4 years ago

If you are using Termux, why don't you build maxima in Termux? Termux probably allows you to use Ptyhon3, so you may be able to use Jupyter lab/notebook. If so, you can use maxima as a kernel for Jupyter.

pouar commented 4 years ago

That's mainly what I've been doing while waiting for this to be updated, although I cross compiled for Termux because my desktop is way faster than my phone, and so Maxima doesn't take ages to finish compiling.