All, Forgive me I am familiar with the C program for the Android/Linux platform. Now I am trying to use the Sourcery G++ Lite Edition
for ARM to build my sample C program and deploy it to the Linux of the Android platform.
Below is the instructions what I follow.
So far it works fine. But I have something I didn't understand well. please review it . thanks.
The Source code is a hello world program.
#include <stdio.h>
int main(int argc,char * argv[])
{
printf("Hello, Android!\n");
return 0;
}
In the development machine command console. run the following commands line.
arm-none-linux-gnueabi-gcc hello.c -static -o hellostatic
adb push hellostatic /data/test
adb shell
cd /data/test
.hellostatic
Hello, Android!
So here is my question.
Can gcc build a executable file from a c source code file? Seems It doesn't need link tool. Is it right? thanks.
Can gcc build a executable file from a c source code file?
yes, of course.
Seems It doesn't need link tool?
no, I extract the following sentences from gcc manual,
GCC is capable of preprocessing and compiling several
files either into several assembler input files, or into one assembler input file; then each
assembler input file produces an object file, and linking combines all the object files (those
newly compiled, and those specified as input) into an executable file.
At default gcc will do complie and link operation, unless you type particular options such like:
gcc -c file.c
this will just compile file.c to file.o
or:
gcc -o file file.c
this will complie file.c to file.o and also link it to make a executable file finally.
Although yanchong had already gave the nice answer , I also found a good read from here. I think it will help to understand the concepts of Compile, Link and Build. Thanks.
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.
A lot of people have mentioned about compiling ffmpeg for android. But I recently tried many of them and did not find them working.
Here is what I tried.
https://github.com/guardianproject/android-ffmpeg-java
but in this I got the following errors.
/home/musil/Desktop/android-ndk-r10c-linux-x86_64/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=/home/musil/Desktop/android-ndk-r10c-linux-x86_64/android-ndk-r10c/platforms/android-3/arch-arm -I../x264 -mfloat-abi=softfp -mfpu=neon -mcpu=cortex-a8 -c -o /tmp/ffconf.6LOSva5W.o /tmp/ffconf.YWZ9ftQ8.c
arm-linux-androideabi-gcc: error trying to exec 'cc1': execvp: No such file or directory
C compiler test failed.
Than I have tried other way mentioned on
http://www.roman10.net/how-to-build-ffmpeg-with-ndk-r9/
but in that I got the following error.
But in that the prefix install is /usr/local/ instead of ./arm/ and arch is x86 instead of arm. And it compiles but no arm folder is created.
Does anyone know how to compile ffmpeg for ndk-r10c.
Will be very helpful if someone can point out what I am doing wrong or how can I build the ffmpeg 2.4.1 for latest ndk.
Thanks
I am not sure why you see that error. I was able to successfully compile FFMpeg and you should be able to get the .so files for all architecture from this link https://github.com/android-native-libraries
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...
Is there any way to have C/C++ compilers directly into the Android device ?
Something like I can adb shell the device and run gcc or agcc or something related to compiling C\C++ src files.
I googled, but there were just speculations, please help in this !
Thanks in Advance :) :)
Shoaib
If you install c4droid you can make an onboard executable by finding the gcc binary and calling it. I also have root on my phone.
On your phone or tablet:
Install c4droid(paid app) and additionally GCC plugin(free).
Install a terminal client. I use Better Term but there are free options as well.
find / -name gcc
/mnt/sdcard/Android/data/com.n0n3m4.droidc/files/gcc/bin/arm-linux-androideabi-gcc
cat > test.c
#include<stdio.h>
int main(){
printf("hello arm!\n");
return 0;
}
./mnt/sdcard/Android/data/com.n0n3m4.droidc/files/gcc/bin/arm-linux-androideabi-gcc test.c -o test
./test
hello arm!
Try C4droid
https://market.android.com/details?id=com.n0n3m4.droidc
or this app
https://market.android.com/details?id=GDE.Main
compile ffmpeg with android ndk r5b.
ffmpeg 0.6.1
android ndk r5b
cygwin 1.7
build reference url : http://www.cnblogs.com/scottwong/archive/2010/12/17/1909455.html
but, ffmpeg ./configure result error! (below config.err file)
check_cc
BEGIN /tmp/ffconf.GlDiY1P8.c
1 int main(void){ return 0; }
END /tmp/ffconf.GlDiY1P8.c
/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/windows/bin/arm-eabi-gcc -fPIC -DANDROID -c -o /tmp/ffconf.1kQLpGaU.o /tmp/ffconf.GlDiY1P8.c
arm-eabi-gcc.exe: /tmp/ffconf.GlDiY1P8.c: No such file or directory
arm-eabi-gcc.exe: no input files
C compiler test failed.
so, i just try test code.
// test.c code
int main(){
return 0;
}
/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/windows/bin/arm-eabi-gcc -fPIC -DANDROID -c -o ./test.o ./test.c
ok!!!! no problem.
but,
cp ./test.c /tmp (copy to /tmp)
/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/windows/bin/arm-eabi-gcc -fPIC -DANDROID -c -o ./test.o /tmp/test.c
arm-eabi-gcc.exe: /tmp/test.c: No such file or directory
arm-eabi-gcc.exe: no input files
fail!!!
difference is only file path. /tmp directory exist, and permission is right. /home/test.c is same result.
what's wrong?
I have had a hard time to get it working in Windows, but finally I've managed to do it!
The previous posts were correct - there's a problem with Cygwin paths and Windows paths.
I have tried the solution described in the post above as the very first thing, but it was not working. Finally I've understand the reason: even if you put into your build_android.sh file the Windows path, the config for FFmpeg still contains the wrong path.
So in my case I have changed partially the config file in FFmpeg root directory from:
#set temporary file name
: ${TMPDIR:=$TEMPDIR}
: ${TMPDIR:=$TMP}
: ${TMPDIR:=/tmp}
to this:
# set temporary file name
#: ${TMPDIR:=$TEMPDIR}
#: ${TMPDIR:=$TMP}
: ${TMPDIR:=D:/InstallTools/Android/Cygwin_Root/tmp}
After this, I got it compiling.
You don't set the tmp directory. You can set it in /etc/profile or just in the terminal with export TMPDIR=/your/tmp/directory.
Notice:
1. If you compile with cygwin, the directory must be like D:/tmp. You can't use /cygdrive/d/tmp.
2. You must have the permission of the folder.
I could not get this to work either, I had the exact same problem. However I was able to compile using "android-ndk-r4". I am not sure at the moment what is causing the problem but if I ever get around to figuring it out I'll post that too.
So for now workaround is to use ndk r4.
I managed to build it, using NDK R6, cygwin. Indeed, it does not support /cydrive/ paths, simply use paths like windows; example below:
NDK=e:/AndroidSDK/NDK6
PLATFORM=$NDK/platforms/android-9/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows
If you have not solved this problem, check the last part of config.log in the ffmpeg directory; it is most likely a path or CC parameter problem.
I have been having the exact same problem with r6. I have tried Lambage's suggestion with r4 but still could not get this to work.
I have been looking into the problem quite a lot and I think I've discovered the reason.
1)configure is calling the android cross compiler which is a windows .exe file.
2)It is calling it through cygwin which uses unix file naming conventions. E.G /cygdrive/c/directory instead of C:\directory
3)It says in the android NDK toolchain documentation that the cross compilers do NOT accept cygwin style filepaths (source: NDK/docs/STANDALONE_TOOLCHAIN.html):
5.1/ Windows support:
The Windows binaries do not depend on Cygwin. The good news is that they
are thus faster, the bad news is that they do not understand the Cygwin
path specification like /cygdrive/c/foo/bar (instead of C:/foo/bar).
I'm still trying to find a way to do this. If i solve it then I'll come back and edit this post...tbc