How to compile a simple OpenCL program in Android? - 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

Related

Visual Studio Android building assembly files into app

We've got a Visual Studio Android solution with (among others) a static library project that contains functionality implemented in assembly. Like:
my.S -> libMine.a -> libMyApp.so
Some hoops (below) have already been jumped through, to get it to compile. Then, the linking of the main app shared library project fails (on both architectures that we care about - x64 and arm64), with undefined references to the functions that are implemented in [the] assembly [file].
It appears that Visual Studio (or its Cross Platform Mobile Dev / Android plug-in) doesn't handle assembly file project items quite correctly - treated as C/C++ Compiler files, it'll error out on the first dot character (i.e. in .text); and the Microsoft Macro Assembler is "not supported on this platform". So I looked into setting up a custom build step, with the following command:
$(ClangToolExe) %(FullPath) --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o
This will preprocess, compile and link - but with the wrong linker: instead of the one for the particular Android toolchain, it'll go for the one in my MinGW install, which doesn't recognise the emulation mode - anyway, that's not the location of my NDK toolchain.
We can skip the linking of the object for now (add -c to the above command). Much to our dismay, the resulting object file still doesn't get added to the static library, as confirmed by {Rest of the toolchain path}ar t libMine.a. And indeed, the library will have undefined symbols for our functions, as shown by {Rest of the toolchain path}objdump -t libMine.a.
Let's add the object file to the resulting library quite manually, as a post build step. Command:
$(ToolChainPrebuiltPath){Rest of the toolchain path}ar.exe ru $(TargetPath) $(IntDir)my.o
objdump -t libMine.a will now show that we've got the symbols. There is however also the *UND*efined pair.
Fast forward:
Adding my.o with ar rub otherObjectThatReferencesMyFunctions.o libMine.a, to have the good symbols show up before the undefined ones doesn't make a difference.
Linking my compiled assembly file with a second custom build step, $(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(IntDir)%(FileName).o -o $(IntDir)%(FileName).o doesn't make a meaningful difference.
Running the linker again on the static library, as a second post-build step $(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(TargetPath) doesn't make a meaningful difference.
The last two steps result in a warning about a missing symbol _start (entry point?). I'm guessing this is in reference to linking an executable, which we don't want.
What am I doing wrong? How can I resolve those undefined references?
What seems to have worked was to:
1, Make sure that the extension of the assembly file is .S, i.e. capital S. This is one of the few instances I've found, where the case of a filename matters on Windows.
2, Configure the project so that the assembly file is built with clang.exe {full/path/to/assembly.S, i.e. %(FullPath)} -c --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o. In the case of VS Android, we need to specify the build output separately, which is the $(IntDir)%(FileName).o part all over again.
3, Run ar as a post build command: {correct toolchain}/ar.exe rus $(TargetPath) {output from assembly compilation}, for each assembly file.
One thing this solution is lacking is detecting [a lack of] changes, meaning that the assembly file will be rebuilt on each compilation, and everything that depends on it.

Issues building openssl for Android

I am following the link here to build Android libraries for openssl:
http://wiki.openssl.org/index.php/Android
Here are my settings in Setenv-Android.sh:
_ANDROID_EABI="arm-linux-androideabi-4.6"
_ANDROID_ARCH=arch-arm
_ANDROID_API="android-16"
The next step is to run the following command:
$ . ./Setenv-Andrhoid.sh
Here is the error I am getting:
Error: FIPS_SIG does not specify incore module. Please edit this script.
There is no mention of how to configure FIPS_SIG in the wiki. Looks like the script is looking for a file or directory called "incore." I searched through my $ANDROID_NDK_ROOT. However, i don't have any "incore" file.
The next command I need to run is the following:
$ ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine \
--openssldir=/usr/local/ssl/$ANDROID_API
Here, is openssldir pointing to absolute /usr/... directory? I am hoping the eventual header and lib files end up in $ANDROID_NDK_ROOT/platform/android-16/arch-arm directory.
Here is the error I am getting:
Error: FIPS_SIG does not specify incore module. Please edit this script.
Oh, you're right. That has been fixed on the wiki.
I thought there was a comment in the script about "it safe to ignore if...", but it appears there is no comment about it either. Sigh....
The same script is used to build both FIPS Capable and non-FIPS version of the OpenSSL library. Its safe to ignore the FIPS_SIG error if you are not building the FIPS Capable library.
Since your are using OpenSSL and Android, it is safe to ignore. If you were following FIPS Library and Android, then it could not be ignored.
Looks like the script is looking for a file or directory called "incore."
For completeness, incore is a script that embeds the HMAC's fingerprint into the program or shared object. The FIPS Object Module will use the embedded HMAC to integrity test itself at startup. Its pretty useless in practice since the key is well known ;)
incore is distributed with openssl-fips-2.0.7.tar.gz and friends. Once you put incore somewhere (the directory tree or, for example, /usr/local/ssl/android-18/bin), you set FIPS_SIG to the filename.
$ ./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine
--openssldir=/usr/local/ssl/$ANDROID_API
Here, is openssldir pointing to absolute /usr/... directory? I am hoping the eventual header and lib files end up in $ANDROID_NDK_ROOT/platform/android-16/arch-arm directory.
--openssldir is the install directory. You should set it to $ANDROID_NDK_ROOT/platform/android-16/arch-arm if that's where you want the library installed.
A little more info: by default, OpenSSL will install itself at /usr/local/ssl. When I build iOS, is use --openssldir=/usr/local/ssl/ios. When I build Android, --openssldir=/usr/local/ssl/android-18 (or android-14, etc).
For example, here's what mine looks like on a Mac Book:
$ ls /usr/local/ssl/
android-14 darwin macosx-x64
android-18 ios macosx-x86

Android ndk-build command returning 'target pattern contains no '%'

I've seen other questions like this, but they don't seem to solve my problem. I am trying to build a C++/Android project on Windows for the first time, and have a few questions:
1) Android NDK docs said cygwin is required, some people on internet say it isn't. I have tried both. But I'm getting many errors in building our project using ndk-build on both cmd.exe and cygwin window. On cygwin it says
*** target pattern contains no '%'. Stop.
I searched that there might be some windows style path there in the make files. Someone said use : $(shell cygpath -u $(path)) instead of $(path) ... It's not helping.
2) Since it's a big project, I wanted to check which all are the places where it's taking a windows style path. But even the simple #echo commands for echoing their values is not working.
#echo $(path)
Some on the internet said we can use this style:
.PHONY: print_vals
print_vals:
<tab>#echo $(path)
but that is not working either. Android NDK development on Windows is difficult :(.
First, Cygwin is not required to run ndk-build on Windows, only to run ndk-gdb, and there is also a python version (ndk-gdb.py) that doesn't require Cygwin anyway.
Second, there must be something weird in your Android.mk file(s). If you don't know how GNU Make works, you should really restrict yourselves to the features described by the NDK documentation (e.g. $NDK/docs/ANDROID-MK.html and $NDK/docs/HOWTO.html)
It's hard to tell exactly why you're seeing this message, but it's very likely because you're using absolute Windows file paths in direct target definitions.
Finally, you cannot use echo to debug Makefiles, use $(info path=$(path)) instead.

Android cross compiling C with no configure file

I've recently started to cross compile a couple of C applications for Android. I've successfully done this for image conversion software using the following pseudo-instructions:
Build the Android toolchain
Compile Automake and Autoconf
Set the CC and CXX environment variables
Build the source package (delete configure, configure.sub, configure.guess, run autoconf configure.ac > configure, run configure with CFLAGS using arm-linux-androideabi, make and make install)
I am now trying to do this for an OCR library written in C. The problem that I am running into is that the library has no configure, configure.guess, or configure.sub. It only has a makefile.
I am not too familiar with C, but is there any different process that I should be following in this situation?
The ./configure step:
CFLAGS=’-march=armv7-a –mfloat-abi=softfp’ ./configure –prefix=/home/user/Downloads/install/usr/local –host=arm-eabi –enable-shared=no –with-modules --enable-delegate-build
is there any different process that I should be following in this situation?
Not really. I mean, if you plan to work with the Android Standalone Toolchain, then all you need to do is:
create the toolchain with the ad hoc target, e.g --platform=android-9
add the toolchain directory to the PATH (for convenience)
export the sysroot path, e.g. export SYSROOT=/tmp/my-android-toolchain/sysroot (for convenience)
set your C compiler (export CC="arm-linux-androideabi-gcc --sysroot $SYSROOT") and archiver, if you target a static library (export AR=arm-linux-androideabi-ar)
Then it all depends about how your Makefile has been written, i.e what are the targets? influential environment variables? etc. But in practice, if the default target fits your need, all you need to do is to run make while overriding the C flags to set the target architecture (ARMv7 here):
make CFLAGS="-march=armv7-a"
That's it. Repeat with other archs (armeabi, x86, etc) if needed.
You can see a complete example for jsmn - a lightweight JSON parse written in C, here: http://git.io/ndk-jsmn.
I've also a set of slides that cover this topic that you may find useful.
According to this article: What does a typical ./configure do in Linux?
configure only checks for system dependencies (if they are missing it exits), checks the type of system you are on, adn then creates a makefile. since you already have a makefile, you should already be able to execute make install.

How to use C libraries from different path with GCC

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

Categories

Resources