Native libs cross compiled from ubuntu linux targeting arm (android) - android

I'm experimenting with native libs cross compiled from ubuntu. What I really want is to be able to compile my c++ libraries and use them in a Xamarin.Android app.
First, I have the arm gcc compiler: arm-linux-gnueabi-gcc. I have a simple lib (libmr.so) that has one function void Print(); that prints something to the console. I'm compiling with:
arm-linux-gnueabi-gcc -Wall -shared -o libmr.so mr.c
When inspecting it using file libmr.so everything seems to be good. However when I'm including it with my android app and try to load it, it is as if it doesn't exist. I'm certain it is there, the path is absolutely correct as I tried to load another lib (libmonodroid.so) from the same folder and it worked.
I tried inspecting both libs to find some kind of a difference:
$ objdump -x libmr.so | grep NEEDED
NEEDED libc.so.6
$ objdump -x libmonodroid.so | grep NEEDED
NEEDED libc.so
... (in addition to other libs)
This is the only difference I'm finding between the two. libmonodroid.so loads properly but libmr.so acts as if it doesn't exist. (I'm using dlopen to load a lib)
EDIT:
I built an executable using the same toolchain, gave me a clue:
Static linking with libc: arm-linux-gnueabi-gcc -Wall -o hi source.c -static. Pushed hi to my android devices and executed it with adb. Result: SUCCESS!
Dynamic linking with libc: arm-linux-gnueabi-gcc -Wall -o hi source.c. Result: it's not even there! Meaning ./hi gives /system/bin/sh: ./hi: not found although it's absolutely there.
So, looks like libc is really the culprit? Maybe I need to link dynamically with not libc.so.6 but with libc.so just like libmonodroid.so is doing?

Check this out for anyone having the same problem. Download the ndk, there's a standalone toolchain for building native libs that run on android that you can extract (you won't need the whole ndk).

I was able to run a basic app on ubuntu 15.04 with this Makefile in the same dir as my hi.c:
$ cat hi.c # create hi.c with favorite editor
#include <stdio.h>
int main(int argc, char** argv) {
int uid = getuid();
int eid = geteuid();
printf("Hello world\n");
printf("You are uid: %d and eid; %d", uid, eid);
return 0;
}
$ cat Makefile # create two line Makefile
CC=arm-linux-gnueabi-gcc
LDFLAGS=-static
$ make hi # build arm based hi executable file
arm-linux-gnueabi-gcc -static hi.c -o hi
$ file hi # check file type
hi: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=17b65e60cdd32449ac237bfd1b8238bfa1d416a0, not stripped
$ adb push hi /data/local/tmp # copy to droid fon
4403 KB/s (593252 bytes in 0.131s)
$ adb shell /data/local/tmp/hi # run hi executable
adb shell /data/local/tmp/hi
Hello world
You are uid: 2000 and eid; 2000
$ uname -a
Linux lenny 3.19.0-28-generic #30-Ubuntu SMP Mon Aug 31 15:52:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Note that I do not have any NDK installed.

Related

Clang linking .so library libc++_shared.so

I'm having an Error in my Native C++ Code in Android NDK Application
My main.cpp
#include <stdio.h>
int main()
{
printf("Hello, world\n");
return 0;
}
The main.c is exactly the same.
If i run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang -pie main.c
then
adb push a.out /data/local/tmp
and
adb shell /data/local/tmp/a.out
all works fine. But if i run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie main.cpp
then
adb push a.out /data/local/tmp
and
adb shell /data/local/tmp/a.out
The error message is:
CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found
Then i tried to run
/home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++ -pie hello1.cpp /home/rip/Music/android-ndk-r19b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so
to link the library, but it doesn't work anyway.
The error message is:
CANNOT LINK EXECUTABLE "/data/local/tmp/a.out": library "libc++_shared.so" not found
That's the expected behavior. Unlike the standard C library (to which your program is linking when building with simple *-clang), C++ is not a system library. You have to make it available on the device just like any other third party library.
Quoted from official documentation:
Note: libc++ is not a system library. If you use libc++_shared.so, it must be included in your APK. If you're building your application with Gradle this is handled automatically.
And:
If you're using clang directly in your own build system, clang++ will use c++_shared by default. To use the static variant, add -static-libstdc++ to your linker flags.
So either link with C++ statically by passing -static-libstdc++ to compiler. Or copy the libc++_shared.so (from <NDK>/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/ in your case) and run like:
adb push a.out libc++_shared.so /data/local/tmp/
adb shell
cd /data/local/tmp/
LD_LIBRARY_PATH=. ./a.out
Other than the LLVM's Standard C++ library discussed above, there's also a limited system C++ runtime (/system/lib(64)/libstdc++.so) which "provides support for the basic C++ Runtime ABI". But "The system STL will be removed in a future NDK release."
I compiled the same "hello world" code in a .c and .cpp file and didn't have the same issue when I pushed the application to my device. I assume you're having the same issue as in this topic:
Application can't find libc++_shared.so
The issue may come from your toolchain or toolchain parameters as you are calling clang manually.
I created a simple project that you can run and test:
android-ndk-example
add_executable( # Sets the name of the library.
ndk_example_c
# Provides a relative path to your source file(s).
main.c
)
add_executable( # Sets the name of the library.
ndk_example_cpp
# Provides a relative path to your source file(s).
main2.cpp
)
In generated cmake script, I can see the following definition for cpp compiler:
rule CXX_COMPILER__ndk_example_cpp
depfile = $DEP_FILE
deps = gcc
command = D:\Users\$USER\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi19 --gcc-toolchain=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/Users/$USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $IN_ABS
description = Building CXX object $out
I write a new Answer for the Solution because i cannot edit my question.
The Solution is the following command for android devices with armv7:
/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi19 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
For aarch64 armv8 the command is:
/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot main.cpp
A CMakeLists.txt file should look as:
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_COMPILER /home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++)
project(Test CXX)
set(CMAKE_CXX_FLAGS "--target=aarch64-none-linux-android21 --gcc-toolchain=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/tony/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot")
set(SOURCES
main.cpp
)
add_executable(Test ${SOURCES})
Then can the app build with
cmake
make
adb push Test /data/local/tmp
adb shell /data/local/tmp/Test

Android not executable: 64-bit ELF file

I'm trying to build a C binary for my Oneplus 3T (LogoInjector) which uses a snapdragon 821 so it's a arm64 device.
When I run:
android-ndk-r13b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc -I android-ndk-r13b/platforms/android-24/arch-arm64/usr/include -c LogoInjector.v1.4.c lodepng
and copy the compiled binary to /system/bin on my phone I get this error:
sush: /system/bin/LogoInjector: not executable: 64-bit ELF file
I also tried the 32 bit toolchain but then it gives me:
sush: /system/bin/LogoInjector: not executable: 32-bit ELF file
I set the binary's permission to 755 just like all the others in /system/bin
Can anyone help me fix this?
Thanks!
The -c switch is instructing the compiler to perform the compilation only step, skipping the linkage stage, producing an object file and not executable. Invoke the
aarch64-linux-android-gcc -I android-ndk-r13b/platforms/android-24/arch-arm64/usr/include LogoInjector.v1.4.c -o lodepng
command instead. It is possible that you will need to specify some linker options (like libraries to link with) in addition to these parameters.
I met this issue when trying to run an application.
Try to run command :"file nameapp". Here I get:
ELF executable, 32-bit LSB arm, dynamic (/system/bin/linker), not stripped.
But my board run command:"file system/bin/sh"
ELF shared object, 64-bit LSB x86-64, dynamic(/system/bin/linker64), for Android 27,BuildID=4a49062467e2958e78ce79839f483302, stripped.
It's different so cannot run.
If you want to run it. Get the file with x86-64.

How to compile Boost 1.61 for Android NDK 11

I want to install compile Boost 1.61 with clang 3.6 for android with the NDK 11 but this software : https://github.com/moritz-wundke/Boost-for-Android isn't updated and doesn't support this versions.
I want to know if anyone has managed to this !
Thank you !
Build boost_1_62_0 for Android-21 under Windows64.
Assuming NDK installed to C:\Programs\Android\sdk\ndk-bundle and boost in c:\boost_1_62_0.
Install mingw: using msys2-x86_64 from MSYS2
Install build tools from mingw prompt (something like this):
$ pacman -S gcc binutils
Create android.clang.jam file in C:\boost_1_62_0\ with such text content:
import os ;
local AndroidNDKRoot = C:/Programs/Android/sdk/ndk-bundle ;
using clang : android
:
C:/Programs/Android/toolchain21/bin/clang++
:
<compileflags>-fexceptions
<compileflags>-frtti
<compileflags>-fpic
<compileflags>-ffunction-sections
<compileflags>-funwind-tables
<compileflags>-Wno-psabi
<compileflags>-march=armv7-a
<compileflags>-mfloat-abi=softfp
<compileflags>-mfpu=vfpv3-d16
<compileflags>-fomit-frame-pointer
<compileflags>-fno-strict-aliasing
<compileflags>-finline-limit=64
<compileflags>-I$(AndroidNDKRoot)/platforms/android-21/arch-arm/usr/include
<compileflags>-Wa,--noexecstack
<compileflags>-DANDROID
<compileflags>-D__ANDROID__
<compileflags>-DNDEBUG
<compileflags>-O2
#<compileflags>-g
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include
<architecture>arm
<compileflags>-fvisibility=hidden
<compileflags>-fvisibility-inlines-hidden
<compileflags>-fdata-sections
<cxxflags>-D__arm__
<cxxflags>-D_REENTRANT
<cxxflags>-D_GLIBCXX__PTHREADS
;
Setup boost from mingw prompt:
$ export NDK=/c/Programs/Android/sdk/ndk-bundle
$ echo ensure msi-installed Python is on path (not msys version):
$ export PATH=/c/Python27:$PATH
$ $NDK/build/tools/make_standalone_toolchain.py --arch arm --api 21 --install-dir /c/Programs/Android/toolchain21
$ ./bootstrap.sh --with-toolset=gcc
$ ./b2 --user-config=android.clang.jam threading=multi link=static \
runtime-link=static toolset=clang-android target-os=linux \
threadapi=pthread --stagedir=android --with-chrono \
--with-program_options --with-system --with-thread --with-random \
--with-regex
Yes, the repository you mentioned is apparently not maintained anymore. The author also seems not to answer any mails on the subject. If you look you'll see that each new boost version supported there required a lot of work (many special flags in the config files). That's presumably why he doesn't have time to maintain it any longer.
I also tried to update to 1.64 using a fork but gave up after countless error messages and instead used a different method based on a crystax script. Its simple and should work for pretty much any version. You can find the details and the script (simple and painless to execute) here: http://silverglint.com/boost-for-android/
Works with clang and gcc.
Also included is a sample app that shows you how to use the boost binaries thus built.

Building OpenSSL for Android (ARMv7) on Win32

How can I build OpenSSL for Android ARM v7 (using Android NDK) on Win32?
Until the OpenSSL's wiki and setenv-android.sh are updated accordingly, I'll publish the recipe here. The required fixes to the process are:
Update setenv-android.sh to support Windows.
Update PATH to use Android NDK's (mingw) GNU make (rather than Cygwin's).
Invoke make with a Windows-style path to Cygwin's perl.
This recipe will be a strange hybrid of Cygwin and mingw (since Android NDK gcc toolchains for win32 are mingw). I'm assuming a Windows x86_64 build of the Android NDK unpacked into c:\android-ndk-r9d, and that you wish to use a gcc 4.8 toolchain.
Install Android NDK (duh!).
Install Cygwin -- make sure to include perl
Start Cygwin shell as an administrator to make sure native symlinks will work.
Within the console, run the following script to set the variables:
export \
CYGWIN=winsymlinks:native \
ANDROID_API=android-14 \
ANDROID_DEV=c:/android-ndk-r9d/platforms/android-14/arch-arm/usr \
PATH=/cygdrive/c/android-ndk-r9d/prebuilt/windows-x86_64/bin:/cygdrive/c/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin:$PATH \
MACHINE=armv7 \
SYSTEM=android \
ARCH=arm \
CROSS_COMPILE=arm-linux-androideabi-
Now, unpack openssl:
tar xzfv openssl-1.0.1i.tar.gz (or whatever your tarball is)
cd openssl-1.0.1i (or whatever your version is)
Make sure you have actual native Win32 (!) symlinks in include/openssl:
cmd /c "dir include\openssl"
You should see something like:
13-Aug-14 05:59 PM <SYMLINK> aes.h [..\..\crypto\aes\aes.h]
13-Aug-14 05:59 PM <SYMLINK> asn1.h [..\..\crypto\asn1\asn1.h]
(etc.)
Now it's time to configure:
./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/foo/bar
Ignore the failure to build (due to failure to find perl). We'll rectify this right away. Do this:
make PERL=$(cygpath -w $(which perl))
Now wait for a few minutes until it builds, and presto, you have your libcrypto.so etc.
Just a couple of comments on my experience with this:
Executing this statement:
PERL=$(cygpath -w $(which perl))
in the cygwin shell allows the shell to interpret the backslashes as escape characters and the build process chokes. To solve this I did the following:
$ echo $(cygpath -w $(which perl))
which produced the windows formatted path to the perl executable:
C:\cygwin64\bin\perl
Then I added this line to the export shown above:
PERL=c:/cygwin64/bin/perl \
There are other ways of doing this, but it worked and headed off the problem with the ./config statement documented above (not finding perl).
Second issue was the -no- statements. After running the configure, the script reports that you'll have to run make depend. I wanted to exclude MD5 (i.e. -no-md5) and when I did the make depend, it errored out with a report that MD5 was disabled. Uhhh, yes, that was kind of the idea, but I just won't use MD5 hashes. I did use the -no-ssl2 and didn't get any complaints after the make depend.
Third issue and this is a mystery. The build broke on compiling crypto because it could not find a symbol that is supposed to be defined in /crypto/objects/obj_xref.h. When I looked at the file, it was empty. Something in the perl script I suppose, but no time to debug right now, since I'm at proof of concept phase. I placed a copy from a patch that I picked up at https://github.com/devpack/openssl-android
After that, my build ran to completion. I've done no testing with this and it is not a trustworthy solution, but it did compile and produce the static libraries that I need for proof of concept for my client.
Just as an update, my shared library built with these libraries loaded fine on my target.

Compiling C code (netcat) to native Android executable

I'm writing a bash script that uses Netcat to serve framebuffer over network connection, but first I need to compile it to native executable. I even got this script to work on a Ubuntu machine, where netcat is installed by default.
I found this https://github.com/android/platform_external_netcat but have no experience in NDK at all. This obviously doesn't use JNI or Java at all so default approach for making Android applications won't get me anywhere.
So the question is. How do I get an executable file from this source code?
If anybody else wants to know, this is from the NDK documentation:
SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/
export CC="$NDK/toolchains/<name>/prebuilt/<system>/bin/<prefix>gcc --sysroot=$SYSROOT"
$CC -o foo.o -c foo.c
More specifically, for the netcat from https://github.com/android/platform_external_netcat
SYSROOT=$NDK/platforms/android-19/arch-arm
CC=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT
$CC -DANDROID -c -o atomicio.o atomicio.c
$CC -DANDROID -c -o netcat.o netcat.c
$CC -o netcat atomicio.o netcat.o
Replace the paths from SYSROOT and CC as appropriate.
Look in the Android sdk under docs/STANDALONE-TOOLCHAIN.html it describes how to use the ndk as standalone compiler which can produce arm binaries.

Categories

Resources