I just wrote a small c file and its header file.
dev_access.c and dev_access.h
I want to link it to the bionic library in android and create a statically/dynamically linked archive file.
My files are in /home/preetam/mydev/
The android sources are in /home/preetam/android_source
The following is my current makefile
CROSS := /home/preetam/bin/CodeSourcery/arm2010/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi
CC := $(CROSS)-gcc
INC_DIR := /home/preetam/android_source/bionic/libc
CFLAGS := -Wall -c -I$(INC_DIR)/include
android_hal: dev_access.o
${CC} ${CFLAGS} dev_access.c -o dev_access.a
clean:
rm -f *.o dev_access.a
I am not sure whats going wrong but header files are not linking and some missing and redefinition errors are coming up.
The following is the Console output:
/home/preetam/bin/CodeSourcery/arm2010/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-gcc -c -Wall -I/home/preetam/android_source/bionic/libc/include -static -c -o dev_access.o dev_access.c
In file included from /home/preetam/android_source/bionic/libc/include/stdio.h:42,
from dev_access.c:1:
/home/preetam/android_source/bionic/libc/include/sys/_types.h:40: fatal error: machine/_types.h: No such file or directory
compilation terminated.
make: *** [dev_access.o] Error 1
First of all, Is my Makefile correct?
Whats the proper way to link your programs with bionic libc ?
How to make the final object an archive?
You should be using these include paths for bionic:
libc/arch-$ARCH/include
libc/include
libc/kernel/common
libc/kernel/arch-$ARCH
ar might have some switches for it...
EDIT: The switch is cr
ar -crv <libname> <source_object>
Related
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
I've two files:
lib.c
#include<stdio.h>
void hi() {
printf("Hi i'm a library function in lib.so\n");
}
and main.c
#include<stdio.h>
#include<dlfcn.h>
/* based on Jeff Scudder's code */
int main() {
void *SharedObjectFile;
void (*hi)();
// Load the shared libary;
SharedObjectFile = dlopen("./lib.so", RTLD_LAZY);
// Obtain the address of a function in the shared library.
ciao = dlsym(SharedObjectFile, "hi");
// Use the dynamically loaded function.
(*hi)();
dlclose(SharedObjectFile);
}
And I've tried to build an executables using the following commands:
export LD_LIBRARY_PATH=pwd
gcc -c -fpic lib.c
gcc -shared -lc -o lib.so lib.o
gcc main.c -ldl
And it works pretty well.
Then I've tried to export my program on Android (Nexus One, with ARM-v7-0a arch) using the following commands:
export LD_LIBRARY_PATH=pwd
arm-none-linux-gnueabi-gcc -c -fpic lib.c
arm-none-linux-gnueabi-gcc -shared -lc -o lib.so lib.o
arm-none-linux-gnueabi-gcc main.c -ldl -o main
adb push main /system/app
The result of executing ./main on the correct folder on my smartphone is just:
./main: not found
even if my file is right there!
Am I missing anything during the cross-compile process? Any help?
I'm using the cross-compiler from CodeSourcery and it works well for static programs without .so libraries.
Thanks
EDIT: as Igor states below, that was a linker issue. This command fixes it:
arm-none-linux-gnueabi-gcc -o test main.c -Wl,--dynamic-linker=/system/bin/linker -ldl
in my very case I need other libraries because in /system/lib/ there are no many .so files.
The "not found" message refers not to the shared object but to the dynamic linker. Linux uses /lib/ld-linux.so.2 (or /lib64/ld-linux-x86-64.so.2 for x64) while Android uses /bin/linker. You can check which dynamic loader your program uses with readelf -l, e.g.:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
You can specify a linker to use with ld's --dynamic-linker switch, but there are likely to be other differences. For example, Android uses a stripped-down libc implementation called bionic, and it may be missing functionality that your program relies on, or have different behavior.
You should use NDK or another Android-targeted toolchain when compiling programs for Android. Even though it's based on Linux kernel, the differences are large enough that Linux-targeted toolchains are not sufficient.
I've two files:
lib.c
#include<stdio.h>
void hi() {
printf("Hi i'm a library function in lib.so\n");
}
and main.c
#include<stdio.h>
#include<dlfcn.h>
/* based on Jeff Scudder's code */
int main() {
void *SharedObjectFile;
void (*hi)();
// Load the shared libary;
SharedObjectFile = dlopen("./lib.so", RTLD_LAZY);
// Obtain the address of a function in the shared library.
ciao = dlsym(SharedObjectFile, "hi");
// Use the dynamically loaded function.
(*hi)();
dlclose(SharedObjectFile);
}
And I've tried to build an executables using the following commands:
export LD_LIBRARY_PATH=pwd
gcc -c -fpic lib.c
gcc -shared -lc -o lib.so lib.o
gcc main.c -ldl
And it works pretty well.
Then I've tried to export my program on Android (Nexus One, with ARM-v7-0a arch) using the following commands:
export LD_LIBRARY_PATH=pwd
arm-none-linux-gnueabi-gcc -c -fpic lib.c
arm-none-linux-gnueabi-gcc -shared -lc -o lib.so lib.o
arm-none-linux-gnueabi-gcc main.c -ldl -o main
adb push main /system/app
The result of executing ./main on the correct folder on my smartphone is just:
./main: not found
even if my file is right there!
Am I missing anything during the cross-compile process? Any help?
I'm using the cross-compiler from CodeSourcery and it works well for static programs without .so libraries.
Thanks
EDIT: as Igor states below, that was a linker issue. This command fixes it:
arm-none-linux-gnueabi-gcc -o test main.c -Wl,--dynamic-linker=/system/bin/linker -ldl
in my very case I need other libraries because in /system/lib/ there are no many .so files.
The "not found" message refers not to the shared object but to the dynamic linker. Linux uses /lib/ld-linux.so.2 (or /lib64/ld-linux-x86-64.so.2 for x64) while Android uses /bin/linker. You can check which dynamic loader your program uses with readelf -l, e.g.:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
You can specify a linker to use with ld's --dynamic-linker switch, but there are likely to be other differences. For example, Android uses a stripped-down libc implementation called bionic, and it may be missing functionality that your program relies on, or have different behavior.
You should use NDK or another Android-targeted toolchain when compiling programs for Android. Even though it's based on Linux kernel, the differences are large enough that Linux-targeted toolchains are not sufficient.
While am compiling live555 for android using ndk, I got stuck at this error!
cd liveMedia ; make
make[1]: Entering directory `/home/jomit/Public/jimjh-liveMedia-for-Android-0c18fdd/liveMedia'
arm-linux-androideabi-ar cr libliveMedia.a -L/home/jomit/Applications/android-ndk-r6/sources/cxx-stl/gnu-libstdc++/libs/armeabi \
Media.o MediaSource.o FramedSource.o FramedFileSource.o FramedFilter.o ByteStreamFileSource.o ByteStreamMultiFileSource.o ByteStreamMemoryBufferSource.o BasicUDPSource.o DeviceSource.o AudioInputDevice.o WAVAudioFileSource.o MPEG1or2Demux.o MPEG1or2DemuxedElementaryStream.o MPEGVideoStreamFramer.o MPEG1or2VideoStreamFramer.o MPEG1or2VideoStreamDiscreteFramer.o MPEG4VideoStreamFramer.o MPEG4VideoStreamDiscreteFramer.o H264VideoStreamFramer.o H264VideoStreamDiscreteFramer.o MPEGVideoStreamParser.o MPEG1or2AudioStreamFramer.o MPEG1or2AudioRTPSource.o MPEG4LATMAudioRTPSource.o MPEG4ESVideoRTPSource.o MPEG4GenericRTPSource.o MP3FileSource.o MP3HTTPSource.o MP3Transcoder.o MP3ADU.o MP3ADUdescriptor.o MP3ADUinterleaving.o MP3ADUTranscoder.o MP3StreamState.o MP3Internals.o MP3InternalsHuffman.o MP3InternalsHuffmanTable.o MP3ADURTPSource.o MPEG1or2VideoRTPSource.o MPEG2TransportStreamMultiplexor.o MPEG2TransportStreamFromPESSource.o MPEG2TransportStreamFromESSource.o MPEG2TransportStreamFramer.o ADTSAudioFileSource.o H263plusVideoRTPSource.o H263plusVideoStreamFramer.o H263plusVideoStreamParser.o AC3AudioStreamFramer.o AC3AudioRTPSource.o DVVideoStreamFramer.o DVVideoRTPSource.o JPEGVideoSource.o AMRAudioSource.o AMRAudioFileSource.o InputFile.o MediaSink.o FileSink.o BasicUDPSink.o AMRAudioFileSink.o H264VideoFileSink.o MPEG1or2AudioRTPSink.o MP3ADURTPSink.o MPEG1or2VideoRTPSink.o MPEG4LATMAudioRTPSink.o MPEG4GenericRTPSink.o MPEG4ESVideoRTPSink.o H263plusVideoRTPSink.o H264VideoRTPSink.o DVVideoRTPSink.o AC3AudioRTPSink.o GSMAudioRTPSink.o JPEGVideoRTPSink.o SimpleRTPSink.o AMRAudioRTPSink.o TCPStreamSink.o OutputFile.o uLawAudioFilter.o RTPSource.o MultiFramedRTPSource.o SimpleRTPSource.o H261VideoRTPSource.o H264VideoRTPSource.o QCELPAudioRTPSource.o AMRAudioRTPSource.o JPEGVideoRTPSource.o RTPSink.o MultiFramedRTPSink.o AudioRTPSink.o VideoRTPSink.o RTPInterface.o RTCP.o rtcp_from_spec.o RTSPServer.o RTSPClient.o RTSPCommon.o RTSPServerSupportingHTTPStreaming.o SIPClient.o MediaSession.o ServerMediaSession.o PassiveServerMediaSubsession.o OnDemandServerMediaSubsession.o FileServerMediaSubsession.o MPEG4VideoFileServerMediaSubsession.o H264VideoFileServerMediaSubsession.o H263plusVideoFileServerMediaSubsession.o WAVAudioFileServerMediaSubsession.o AMRAudioFileServerMediaSubsession.o MP3AudioFileServerMediaSubsession.o MPEG1or2VideoFileServerMediaSubsession.o MPEG1or2FileServerDemux.o MPEG1or2DemuxedServerMediaSubsession.o MPEG2TransportFileServerMediaSubsession.o ADTSAudioFileServerMediaSubsession.o DVVideoFileServerMediaSubsession.o AC3AudioFileServerMediaSubsession.o QuickTimeFileSink.o QuickTimeGenericRTPSource.o AVIFileSink.o MPEG2IndexFromTransportStream.o MPEG2TransportStreamIndexFile.o MPEG2TransportStreamTrickModeFilter.o DarwinInjector.o BitVector.o StreamParser.o DigestAuthentication.o our_md5.o our_md5hl.o Base64.o Locale.o
arm-linux-androideabi-ar: -L/home/jomit/Applications/android-ndk-r6/sources/cxx-stl/gnu-libstdc++/libs/armeabi: No such file or directory
make[1]: *** [libliveMedia.a] Error 1
make[1]: Leaving directory `/home/jomit/Public/jimjh-liveMedia-for-Android-0c18fdd/liveMedia'
make: *** [all] Error 2
The error states:
arm-linux-androideabi-ar: -L/home/jomit/Applications/android-ndk-r6/sources/cxx-stl/gnu-libstdc++/libs/armeabi: No such file or directory
But I do have the directory /home/jomit/Applications/android-ndk-r6/sources/cxx-stl/gnu-libstdc++/libs/armeabi on my filesystem. It is obtained by running the script make-standalone-toolchain.sh from the tools directory of android ndk. To avoid all permission problems, I gave all permissions to ndk and its subdirectories using chmod 777 -R /home/jomit/Applications/android-ndk-r6/. My question is how do I solve this error?
NOTES:
liveMedia-for-Android from github is the live555 android port I am using.
I am running 64-bit Fedora 16.
Following is my android.sh file which I am running to compile live555:
#!/bin/sh
#
# Builds libraries for Android
# Written by Jiunn Haur Lim <jim#jh-lim.com>
export PATH="${NDK_ROOT}/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/:${PATH}"
SYS_ROOT="${NDK_ROOT}/platforms/android-8/arch-arm"
PREF="arm-linux-androideabi-"
export LD="${PREF}ld --sysroot=${SYS_ROOT}"
./genMakefiles android
make
exit 0
Following is the config.android file:
CROSS_COMPILE ?= arm-linux-androideabi-
SYS_ROOT = $(NDK_ROOT)/platforms/android-8/arch-arm
COMPILE_OPTS = $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -fPIC --sysroot=$(SYS_ROOT) -DLINUX -DANDROID
C = c
C_COMPILER = $(CROSS_COMPILE)gcc
C_FLAGS = $(COMPILE_OPTS) -lc -lgcc
CPP = cpp
CPLUSPLUS_COMPILER = $(CROSS_COMPILE)g++
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1 -lstdc++ -lsupc++ \
-I$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/include \
-I$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include \
-L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi
OBJ = o
LINK = $(CROSS_COMPILE)g++ --sysroot=$(SYS_ROOT) -o
LINK_OPTS = -L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi
CONSOLE_LINK_OPTS = $(LINK_OPTS)
LIBRARY_LINK = $(CROSS_COMPILE)ar cr
LIBRARY_LINK_OPTS = $(LINK_OPTS)
LIB_SUFFIX = a
LIBS_FOR_CONSOLE_APPLICATION =
LIBS_FOR_GUI_APPLICATION =
EXE =
Both files - android.sh and config.android - are the ones already available with the port.
I really appreciate any help since Google has a little bit lack of knowledge on this problem :)
The issue is that GNU ar (arm-linux-androideabi-ar in this case) does not accept the -L option, which causes it to treat that as a file (rather than a path option that should go to gcc/ld while dynamic linking).
ar compiles a static library from a set of object files, and thus does not need/honour the -L option.
My goal is to compile the kiss_fft libraries to use in JNI for android development.
However to begin with, I am attempting to just use the kiss_fft libraries on my linux machine in C.
when using Kiss_fft.c or Kiss_fftr.c from Kiss_fft (Kissfft
)to calculate the DFT. How exactly do you compile their libraries into your own file. In the top of my source C file, I #include kiss_fft.h and #include kiss_fftr.h, and also either place the kiss_fft souce code in my project root directory or in /usr/include/ in linux, then I compile with a makefile similar to this one:
#Makefile
#ARGS = -g -ansi -pedantic -Wall -Werror -O1
ARGS = -g -lsndfile -O1 -lm
FILES = spec_subv4.o kiss_fftr.o kiss_fft.o
spec_sub: $(FILES)
gcc $(ARGS) $(FILES) -o spec_sub
spec_subv4.o: spec_subv4.c
gcc -lsndfile $(ARGS) -c spec_subv4.c -o spec_subv4
kiss_fftr.o: kiss_fftr.c kiss_fftr.h kiss_fftr.h _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fftr
kiss_fft.o: kiss_fft.c _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fft
Looking through all the kiss_fft source files, I wrote this make file to build all the dependencies. However I still get
undefined reference to kiss_fft
undefined reference to kiss_fft_alloc
Which are internal functions of the kiss_fft libs.
Any help would be appreciated. Thanks
Your makefile targets never actually compile kiss_fft.c
e.g.
kiss_fft.o: kiss_fft.c _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fft
compiles kiss_fftr.c not kiss_fft.c
I think symbol/function kiss_fft, kiss_fft_alloc are not part of any libary included.
Few things must be checked before you link:
Check if symbols are available in library sndfile
nm | grep "kiss_fft"
Check if you have mentioned the PATH for library in make file.
Include your library path as
-L
Check if prototypes of these functions are in harder files
Include them with
-I
If any C,C++ combination code is used
Use extern "C" sytax.
prototypes of functions must match with prototypes included in library.
Worked it out, thanks for the input. I simply just compiled with:
gcc $# -g -lsndfile -lm -std=gnu99 spec_sub_kiss.c kiss_fft.c kiss_fftr.c -o spec_sub_kiss
Where the -lsndfile is the libraries to read and write some .wav files for my project.