How to use C libraries from different path with GCC - android

I am using Android NDK GCC toolchain to compile a project as command-line.
My gcc location is
/opt/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc
And I am using the gcc option
--sysroot=/opt/android-ndk/platforms/android-8/arch-arm/
There is no problem when building Hello World. But for this project, during linking, it produces the error:
/opt/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld:
crtbegin_static.o: No such file: No such file or directory
Actually, the "crtbegin_static.o" is located in
/opt/android-ndk/platforms/android-8/arch-arm/usr/lib
If I put it to
/opt/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3
then this problem can be solved.
Is there anyway to make gcc to locate the crtbegin_static.o correctly.

Finally, I have found the solution. It can be solved by passing the "--sysroot=" option again to the linker, not compiler only, using
-Wl,--sysroot=/opt/android-ndk/platforms/android-8/arch-arm/

There is a -L option which specifies the directories searched for -l.
http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
http://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html

Related

How to compile a simple OpenCL program in Android?

I've spent many hours today trying to accomplish this seemingly very simple task so my frustration may seem strange to you.
I want to "run"/execute a program that contains OpenCL functions on my Samsung Galaxy S7 (Exynos SoC). Support for OpenCL shouldn't be an issue because:
1) It's a well supported flagship phone from a well-known manufacturer
2) libOpenCL.so is present in /system/vendor/lib/libOpenCL.so
3) OpenCL-Z reports a valid platform and device (GPU only for some reason)
Things that I tried:
Rooted the phone.
Installed cppdroid.
Tried to compile a simple program that contains references to standard OpenCL functions like clGetPlatformIDs().
Header files should be included somewhere, but I could not for the life of me find where to put them (using the same path where cppdroid stores standard header files did not work), so I manually included the headers in the .c file itself, making it barely editable on the phone itself.
My understanding is that I should link the library (libOpenCL.so) to the output of gcc during the linking phase. There seems to be an option to do that in cppdroid, under "Settings" "Project settings" "Link options" so I add:
-L/system/vendor/lib/libOpenCL.so
to that field. However compilation still fails and I'm getting "undefined references to clGetPlatformIDs()" as if I hadn't included the library at all.
After searching online for a solution, a possible remedy (see below) proved useless:
-Wl,--whole-archive -L/system/vendor/lib/libOpenCL.so
I thought I'd get gcc on its own since this is the compiler used by cppdroid and try to compile that way. Found out that it's supposed to be deprecated, and replaced by "clang". But cppdroid does include gcc, so I navigated to the folder containing the executable (I believe it's an executable, there seem to be no extensions here, and I'm a Windows person) which appears to be:
/data/data/name.antonsmirnov.android.cppdroid/sdk/gcc#4.8#2/bin
and tried to "execute" gcc-4.8 (which appears to be the executable compiler) from termux (a terminal emulator for Android). Much to my surprise I got the error message:
sush: gcc-4.8: not found
Even though ls -1 lists the file normally!
I tried various other stuff that did not work, but here's my question:
How do I go about compiling a simple OpenCL program that I've written in C, so as to execute it on my Android mobile device?
Why do I get the
sush: gcc-4.8: not found
error message?
My understanding is that I should link the library (libOpenCL.so) to the output of gcc during the linking phase. There seems to be an option to do that in cppdroid, under "Settings" "Project settings" "Link options" so I add:
-L/system/vendor/lib/libOpenCL.so
to that field. However compilation still fails and I'm getting "undefined references to clGetPlatformIDs()" as if I hadn't included the library at all.
You need to add -lOpenCL and -L/system/vendor/lib to the linker flags. The second option may not be required, as this directory should be in a default search path already.
First -L provides a search directory for libraries to link, you should be using -L/system/vendor/lib you can use -l to link to a library in your case -lOpenCL without the lib prefix.
I got it working on my Samsung S9+ Exynos phone. Here is what I did to use OpenCL in the Termux app:
apt update
apt upgrade
apt autoremove
apt install vim openssh clang git
vim ~/.bashrc
# press the i key, then paste the line below, then save and exit with :wq
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/vendor/lib64:/system/vendor/lib64/egl
# restart Termux
exit
And finally, to compile a C++ OpenCL program with headers as described here:
cd Test/src
g++ *.cpp -o Test.exe -std=c++11 -pthread -w -I./OpenCL/include -L/system/vendor/lib64 -lOpenCL
./Test.exe
To install clinfo do the following:
apt install cmake make
cd ~
mkdir opencl
cd ~/opencl
git clone https://github.com/KhronosGroup/OpenCL-Headers
cd ~/opencl/OpenCL-Headers
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=$PREFIX
cmake --build build --target install
cd ~/opencl
git clone https://github.com/Oblomov/clinfo
cd ~/opencl/clinfo
make OS=Android
./clinfo

Bitbucket Pipelines: No toolchains found in the NDK toolchains folder for ABI with prefix: aarch64-linux-android

I am totally new to CI with Bitbucket Pipelines and was currently setting up pipeline with the help of this article. My builds are failing due to this error
"No toolchains found in the NDK toolchains folder for ABI with prefix: aarch64-linux-android"
Can anyone help me fixing this?
Today I run into the same issue like you. I also followed the blog post you mentioned. Whatever. I'm happy to report you: I fixed it and found a "solution"! 😄
The funny part is: The solution so dumb as simple. The only thing you have to do is to unset (or remove) the NDK environment variable (or directory).
The magic line is:
- unset ANDROID_NDK_HOME
Which means that my final bitbucket-pipelines.yml looks like:
image: uber/android-build-environment:latest
pipelines:
default:
- step:
script:
- unset ANDROID_NDK_HOME
- ./ci/accept_android_license.sh
- ./gradlew :app:testDebugUnitTest
Why does it fix the issue?
To be honest. I don't know 😅. But I found out that the ubers android-build-environment install the NDK for you.
I found some answers - like here - to install the NDK separately again. But I thought about the following: Why the hell should I install/update the NDK if my project doesn't use it? So I tried to remove the NDK folder (which according to the Dockerfile located at /usr/local/android-ndk) and everything works 🎉.
Why unsetting then?
You can't remove the android-ndk dir because you don't have permission to do it. But you can delete the content from it. That is the reason why it worked with rm -rf /usr/local/android-ndk. But then - with the setting of ANDROID_NDK_HOME but without any content in there you got the error message (while building):
./gradlew :app:testDebugUnitTest
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /usr/local/android-ndk.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.
unset the environment variable fix that warning as well.
Important:
Obviously that is not the best solution. If your App uses the NDK this solution will not help. To remove some environment variables "from a Docker image" in a CI script is also not the best solution. Maybe the image need the variable later (don't know if that is possible in Docker... but you know what I mean 😉). But it will "temporary" fix the problem and since the android-build-environment is unmaintained (not update since a year) anyway I would not put to much effort in fixing the image...
Note: The link to the uber:android-build-environment GitHub page refers to a single (currently the last) commit. If someone read that in the future the link is still active and correct but maybe the master branch have changed.
cd .../AndroidSdk/ndk-bundle/toolchains
ln -s aarch64-linux-android-4.9 mips64el-linux-android-4.9
ln -s arm-linux-androideabi-4.9 mipsel-linux-android-4.9
You need to download android ndk and install the standalone toolchain similar like this
$NDK/build/tools/make_standalone_toolchain.py \
--arch arm --api 21 --install-dir /tmp/my-android-toolchain
Sometimes you have to create the environmental variable for the toolchain.

How to build Alsa Utils with NDK

My goal is to compile amixer from alsa-utils-1.0.29 using Android NDK to an executable I can use on Android device.
I can't find a way to build it using ndk-build nor can I find any documentation on how to achieve this.
Is there a way to accomplish that?
Edit: I tried cross-compiling alsa-lib and alsa-utils on Ubunto using this guide, but result amixer does not run on Android (says no such file or directory).
When I use ndk-build amixer does not compile (keeps complaining on undefined references).
Edit 2:
The steps I did that failed were as following:
- Downloaded alsa-lib and alsa-utils from alsa project site
- Compiled alsa-lib using Android.mk based on this Android.mk - succeeded
- Compiled alsa-utils based on this SO question: alsa-utils + ndk-build not working
- At first I constantly got errors saying there is no rule for building amixer.o. Only replacing $(LOCAL_PATH) with hard-coded path resolved it
- Now, when compiling - although Android.mk points to all required includes, I got lots of undefined reference errors such as: "undefined reference to 'snd_ctl_card_info_sizeof'"
What is the way to build alsa-utils in a way it can be used on Android?

How to remove libusb from Android standalone toolchain?

I'm trying to compile a tool that uses libusb with modified libusb for android.
Modified libusb was compiled and installed to /usr/local/lib as expected.
The problem is that standalone toolchain already contains libusb and it hurts linking/compilation.
./configure
Returns:
...
checking for usb_get_string_simple in -lusb... yes
...
So libusb if found okay.
But with standalone toolchain:
export CROSS_COMPILE=arm-linux-androideabi
export CC=${CROSS_COMPILE}-gcc
export CXX=${CROSS_COMPILE}=g++
export NDK=/softdev/android-ndk-r8e
export ANDROID_NDK_ROOT=/softdev/android-ndk-r8e
export SYSROOT=$NDK/platforms/android-8/arch-arm
export PATH=/softdev/arm-toolchain/bin:$PATH:/softdev/android-ndk-r8e/platforms/android-8/arch-arm
./configure --build=x86-unknown-linux-gnu --host=arm-linux-androideabi --target=arm-linux-androideabi
It returns:
...
checking for usb_get_string_simple in -lusb... no
...
how to make it working with standalone toolchain?
libusb-0.1 is used
Well, finally i was able to fix it.
the tool configure.ac file was not written in account to using libusb-compat (but for only libusb-0.1).
So i solved it by adding dependency while searching libusb-0.1 (-lusb-1.0):
AC_CHECK_LIB([usb], [usb_get_string_simple], [have_libusb=yes], [], [-lusb-1.0])
2. Another problem was to make AC_CHECK find libs not in standard system /usr/local/lib folder as modified library interface was a bit different
and it tried to gcc with system one while searching with AC_CHECK_LIB. I used CPPFLAGS to set the right libs path

Android GCC Makefile, want to build shared lib and linking in static lib, without "ndk-build"

I had some experience of android but know almost nothing of GCC Makefile. Here is what I need,
working on mac osx or linux, using android ndk toolchain, build an android shared library .so (a jni lib), linking in a prebuilt static library (already built for android). In static lib, I need logcat functions and C funcs such as sprintf. So no "ndk-build" in the process. The reason I have to do this, when linking in the static lib, a special linker is required to replace the standard arm-eabi-gcc, and the standard linker will be rolled back later.
I know that I need to set following environment variables such as:
ANDROID_NDK,
PATH=$PATH:"$ANDROID_NDK/build/prebuilt/darwin-x86/toolchain/arm-eabi-4.4.0/bin"
MACHINE=armv7l
SYSTEM=android
ARCH=arm
CROSS_COMPILE="arm-eabi-"
ANDROID_DEV="$ANDROID_NDK/platforms/android-8/arch-arm/usr"
HOSTCC=gcc
All I need is a sample Makefile, so that I can run "make" to build a .so by linking in a .a, and other necessary android and c libs.
Thanks
Try running ndk_build V=1 and recording the commands it issues in verbose mode. Then issue comparable commands to your custom linker.
Beware the commands might change for a different ndk version.

Categories

Resources