JHC is a Haskell compiler which portable generates C code and then invokes a compiler backend to make an executable.
I need to dump the header files and libraries for JHC's runtime system, so the android ndk can use it to compile the generated C code.
Alternatively, I need to figure out how to link the android API into JHC.
Basically, how can I plug JHC into the android ndk backend?
Edit: I've made a standalone compiler using one of the ndk's build tools that JHC can use, "build/tools/make-standalone-toolchain.sh" . Now I need to figure out a way for JHC to compile my program into a shared object library, and how to get JHC to not demand a "main" function.
Edit2: I have the following targets.ini and compile script. Strangely the shared library fails to load.
[android]
cc=arm-linux-androideabi-gcc
cflags+= -shared -fPIC -rdynamic -Wno-all
gc=static
executable_extension=.so
merge=mle32
and
#!/bin/sh
jhc --cross -mandroid \
--main=Main.android_main \
hs/Main.hs -o libs/armeabi/libnative-activity &&
ant debug &&
ant debug install
I figured out the problem.
I didn't put the function call "app_dummy()" at the start of my "android_main" function.
Related
I am new to this build system, but I've spent dozens of hours trying to get qmake + clang to produce a working android binary. I would appreciate any help or advice. Here is as simple an example as I can come up with:
First, here is a working build command. It gives me a shared object that I can call from android (with Unity, using C# native interops):
C:\Users\deltav\AppData\Local\Android\Sdk2\ndk\21.3.6528147\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe ^
-target aarch64-none-linux-android21 -shared -v ^
-DANDROID_ABI=arm64-v8a -DANDROID_ARM_MODE=arm -DANDROID ^
M:\simpleExample\simpleExample.c ^
-o M:\simpleExample\libsimpleExample.so
Here is the verbose output of running that command: https://pastebin.com/18HcnDYh
On the other hand, here is the simpleExample.pro file that is NOT giving me a good binary: https://pastebin.com/wxrx6Myc
Here is the qmake output for building in release mode: https://pastebin.com/KWavwrb7
As you will know, qmake uses a kit to execute the project. My kit: https://imgur.com/a/Ehtmgin
The specific issue that has pushed me down this debugging path is from C# trying to load my shared object like this:
[DllImport("simpleExample")]
public static extern float getSpeedY();
The error that I get is this:
"DllNotFoundException: Unable to load DLL 'simpleExample': The
specified module could not be found."
Again, this error is not an issue if I just build from the CLI without qmake. I do not beleive this is a unity or C# error, as I worked the problem from that side first.
What I have tried so far:
I have used multiple ELF & DWARF tools to compare the ABIs of the generated binaries, which all told me the binaries were identical.
I tweaked and shaved down the clang calls that qmake generated until I got a vaild build command. Unfortunately I can't just replace qmake with the complile command because there are other projects that I need to apply this fix to.
QMake version 3.1
Ironically, CMake basically works out of the box.
Answer: Looking at the clang linking call, you can see QMake 3.1 was adding "libc++shared" as a dependency. I'm not sure why, as this was a C project.
The equivalent CMake project did not do this.
Packaging libc++shared with my binary fixed the issue.
this is my current problem. Now I am trying to port a x86 based project to android. But this project need pthread library support, and can't pass configuration stage.
Command:
./configure --build=${BUILD_SYS} --host=arm-eabi --prefix=${PREFIX} --disable-rpath --disable-libasprintf --disable-java --disable-native-java --disable-openmp --disable-curses
Compiler and compile flags:
export CFLAGS="--sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${PREFIX}/include -I${NDK}/sources/android/support/include -pthread -fPIE -DANDROID -Wno-multichar"
export CXXFLAGS=${CFLAGS}
export CPPFLAGS="--sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${PREFIX}/include -I${NDK}/sources/android/support/include -pthread -DANDROID -DNO_XMALLOC -mandroid"
export LIBS="-lc -lgcc -lstdc++ -ldl"
export LDFLAGS="-Wl,-L${SYSROOT}/usr/lib -L${PREFIX}/lib -L${NDK_TOOLCHAIN}/lib"
Error Msg:
checking for WIN32... no
checking for Mac... no
checking for Linux... compile in linux
checking for uuid_generate in -luuid... yes
found library uuid
checking for pthread_create in -lpthread... no
configure: error: *** Unable to find pthread library
Please help with it: how to attach right flags? OR How to cheat to autoconf? OR How to cross compile libpthread? AND pass the compile finally.
POSIX threads (pthreads) for Android :
The android libc, bionic, provides built-in support for pthreads, so no
additional linking (-lpthreads) is necessary. It does not implement full
POSIX threads functionality and leaves out support for read/write locks,
pthread_cancel(), process-shared mutexes and condition variables as well as
other more advanced features.
So not required to add -lpthreads and remove check also.
I'm working on a project, where I need to modify dd for Android, but I can't figure out how to build it. I've tried a simple way using arm-linux-gnueabi-gcc dd.c -o dd, but of course that wouldn't work. And I also can't find a makefile.
Is it possible to just build dd or do I need to build toolbox or the whole system? In any case, how do I do that?
I found the source code here.
EDIT:
Is it possible to build the GNU core utils for arm? I tried using ./configure --host=arm-linux --target=arm-linux && make, but file dd still returns executable, x86-64.
After lots of googling I was finally able to build the GNU core utils for arm.
I first had to set the environment variables CC and CXX to arm-linux-gnueabi-gcc and LDFLAGS to -static. Then I just ran ./configure --target=arm-linux --host=arm-linux && make and that's it.
I have a really simple helloworld.cpp program
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
And I'm trying to compile it for android x86 with the cross-compiler from the toolchain:
/Users/me/android-ndk-r8/toolchains/x86-4.4.3/prebuilt/darwin-x86/bin/i686-android-linux-g++ helloworld.cpp -L "/Users/me/android-ndk-r8/sources/cxx-stl/stlport/libs/x86/" -lstlport_static
However, I get errors:
helloworld.cpp:2:20: error: iostream: No such file or directory
Any idea why?
Check the documentation.html file included with the NDK, under "Standalone Toolchain". It says that if you invoke the compiler in this way you won't be able to "use any C++ STL". However it is possible, as the documentation explains, if you first create a "customized" toolchain installation, using something like the following command:
$NDK/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=/tmp/my-android-toolchain --arch=x86
where $NDK is the path to your NDK directory. Note the --arch=x86 which means that the toolchain is prepared specifically for the x86 Android. This prepares what you need in one directory, including the STL headers and folders. You should then be able to use -lstdc++ to link against the STL (static version), i.e. something like:
/tmp/my-android-toolchain/bin/i686-android-linux-g++ helloworld.cpp -lstdc++
For a more complete explanation, please see the NDK documentation.
The NDK documentation is not entirely accurate, at least not currently. In fact, it states when using the prebuilt toolchain "You won't be able to use any C++ STL (either STLport or the GNU libstdc++) with it.", but this is out of date. I created a small hello world program using the include with the same error. It can be solved without creating your own toolchain though, which is nice if you don't want to have to add one more step to your configuration process and allows you to always use the latest SDK platform without creating a new toolchain every time.
The NDK ships with the source code for several versions of standard C++ libraries: GAbi++, STLport, and GNU STL. Each flavor comes with prebuilt shared and static libs as well. My example below will use stlport.
To use the stand-alone toolchain at its installed location, you can do something like this:
export CXX='$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ --sysroot="$NDK_ROOT/platforms/android-19/arch-arm"'
This, for example, would set your CXX compiler to compile ARM on the OS X system using SDK platform level 19. This much you probably already knew. Also, you would want to export your CC, CPP, LD, AR, and RANLIB if you use it. I also personally create an envar for READELF.
To add support for C++ libs, you could do something like follows:
$CXX helloworld.cpp -I$NDK_ROOT/sources/cxx-stl/stlport/stlport -L$NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi -lstlport_shared
Note that this will link the libstlport_shared.so which will now be required at runtime, so you may need to add a relative path to the command above to support that, depending on your APK structure. If you want to just test this simple case, you can just run this on the emulator as follows:
adb push a.out /data
adb push $NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi/libstlport_shared.so /data
adb shell
# su
# cd /data
# chmod 777 a.out
# ./a.out
To get rid of the headache of dealing with shared library paths, you can also statically link the C++ library in by changing "-lstlport_shared" to "-lstlport_static". There are some consequences of doing this, as explained in the NDK Dev Guide. The biggest issue is due to having the static library linked in multiple places, causing:
- memory allocated in one library, and freed in the other would leak or even corrupt the heap.
- exceptions raised in libfoo.so cannot be caught in libbar.so (and may simply crash the program).
- the buffering of std::cout not working properly
A useful tool is also included to see what dependencies your program has, the readelf tool.
To see what other shared libraries your program requires, you can run the following:
$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-readelf -a a.out | grep NEEDED
Other cool standard tools:
addr2line - convert a stack trace address to a line of code
nm - Displays the symbol table
objdump - displays info on an object
i call one of the functions from gnustl after it runs fine from prebuilt aosp arm-linux-androideabi-gcc --std=c++11 and after crashing error i cant get a backtrace from logs or reason, my hope is turning to crossbuilt qemu-linux-user to run host compiled i686 binary on the arm, difficulty is interacting with crosshost libs aapt from adt always crashes on any other than platform specific libs, unless kernel module packaged update is possible...
I've read in the gcc documentation that it supports building android binaries with the -mandroid and -mbionic switches. First I tried it with the native gcc built from svn. Result:
dancsi#dancsi-VirtualBox:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../source/configure --enable-threads --disable-nls
Thread model: posix
gcc version 4.7.0 20110611 (experimental) (GCC)
dancsi#dancsi-VirtualBox:~$ g++ test.cpp -mandroid -o test.out
dancsi#dancsi-VirtualBox:~$ file test.out
test.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
Basically, it failed. Next, I tried to compile the same gcc sources with target=arm-linux-androideabi, (without defining sysroot,...), and it passed the configuration, but failed to build saying pthread.h is not found:
In file included from ../.././gcc/gthr-default.h:1:0,
from ../../../combined/libgcc/../gcc/gthr.h:160,
from ../../../combined/libgcc/../gcc/unwind-dw2.c:37:
../../../combined/libgcc/../gcc/gthr-posix.h:41:21: fatal error: pthread.h: No such file or directory
compilation terminated.
So, does anybody have the instructions for how to use gcc to build android binaries (I don't want to use code sourcery or android-ndk)?
EDIT:
my configure options
configure --target=arm-linux-android --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-libssp --disable-libgomp --disable-nls --enable-languages=c,c++,java
I had exactly the same problem as described by dancsi while trying to compile my own cross compilation tool chains for Android (I wanted to build a 32 bit variant of them so I don't need to buy a 64 bit PC or do my android stuff in a VM).
I am using the tool chain sources from the official AOSP tool chain repo:
repo init -u https://android.googlesource.com/toolchain/manifest
The solution is to use the following 2 extra configure options: --with-headers and --with-libs. I've got this solution by reading the following file: [android-toolchain-repo]/build/README:
The other way is to specify the headers and libraries with --with-headers and
--with-libs separately. If you configure your tree with a prefix. The headers
and libraries will be copied to the install directory specified by the prefix.
For the values of those 2 extra parameters I used [android-src-repo]/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib and [android-src-repo]/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include. [android-src-repo] is referring to my repo checkout of the base AOSP sources (in my case I am on the android-4.2.2_r1 branch of it).
The end-result of the two configure statements I need are the following:
./configure --target=arm-eabi --host=i686-linux-gnu --build=i686-linux-gnu --disable-gold \
--with-gcc-version=4.6 --with-binutils-version=2.21 --with-gmp-version=4.2.4 --with-mpfr-version=2.4.1 \
--with-gdb-version=7.3.x --with-gold-version=2.21 --prefix=/tmp/toolchain --disable-multilib \
--with-libs=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib \
--with-headers=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include \
--program-transform-name='s&^&arm-eabi-&' --with-arch=armv5te --disable-option-checking
./configure --target=arm-linux-androideabi --host=i686-linux-gnu --build=i686-linux-gnu --enable-gold \
--with-gcc-version=4.6 --with-binutils-version=2.21 --with-gmp-version=4.2.4 --with-mpfr-version=2.4.1 \
--with-gdb-version=7.3.x --with-gold-version=2.21 --prefix=/tmp/toolchain \
--with-libs=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib \
--with-headers=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include \
--program-transform-name='s&^&arm-linux-androideabi-&' --disable-option-checking
Notice the extra --disable-option-checking argument which was necessary for configure to accept all arguments!
This long list of arguments was constructed by checking the original configure arguments passed for the default 64 bit version of the 4.6 gcc toolchain. This can be checked in the SOURCES files available in [android-src-repo]/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6 and [android-src-repo]/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6.
In the same files, git tags can be found, so I also checkout those specific version in my [android-toolchain-repo]. For the extra modules needed by gcc, like gmp/mpfr/gdb..., I extracted the correct versions of the tar-balls available in [android-toolchain-repo]/gmp|mpfr|gdb. This was the easiest way I could find out, for my original configure statement to be able to pick up those modules.
The same technique as described above also allowed me to compile a 32 bit variant of the latest gcc 4.7 tool chain (currently being used on the MAIN branch of AOSP). The configure options were of course different in this case.
In file included from ../.././gcc/gthr-default.h:1:0,
from /mnt/network/source/gcc/libgcc/../gcc/gthr.h:160,
from /mnt/network/source/gcc/libgcc/../gcc/unwind-dw2.c:37:
/mnt/network/source/gcc/libgcc/../gcc/gthr-posix.h:41:21: fatal error: pthread.h: No such file or directory
compilation terminated.
make[2]: *** [unwind-dw2.o] Error 1
make[1]: *** [all-target-libgcc] Error 2
make: *** [all] Error 2
I'm getting the same error as you, but I'm not compiling for Android. I'm trying to build w64-mingw32 compiler.
AR=x86_64-w64-mingw32-ar RANLIB=x86_64-w64-mingw32-ranlib
../gcc-4.5.1/configure --prefix=/tools \
--with-local-prefix=/tools --enable-clocale=gnu \
--enable-shared --enable-threads=posix \
--enable-__cxa_atexit --enable-languages=c,c++ \
--disable-libstdcxx-pch --disable-multilib \
--disable-bootstrap --disable-libgomp \
--without-ppl --without-cloog --build=$MACHTYPE --host=$MACHTYPE --target=x86_64-w64-mingw32
My response is so you know its not just Android, the trouble is more general then just building for the ARM architecture.
I think its a c++ issue, cause I had/have no trouble with building a c compiler alone.