I am trying to build libraw as a Android shared library. It looks the lib is too complex to use with Android.mk etc, or better: I am not capable yet of doing that.
I tried the route of using a standalone toolchain from the NDK, but I am getting stuck when compiling this lib.
This is the path I take to compile the lib. Please point out if I am making obvious errors:
I downloaded the ndk.
ran: make-standalone-toolchain.sh
Added the bin folder of that standalone toolchain as first item in my PATH.
Ran ./configure with --host=arm-linux-androideabi. This succeeded
Ran make, here it crashed very fast.
LibRaw-0.14.4$ make
depbase=`echo internal/dcraw_common.lo | sed 's|[^/]*$|.deps/&|;s|\.lo$||'`;\
/bin/bash ./libtool --tag=CXX --mode=compile arm-linux-androideabi-g++ -DPACKAGE_NAME=\"LibRaw\" -DPACKAGE_TARNAME=\"libraw\" -DPACKAGE_VERSION=\"0.14.4\" -DPACKAGE_STRING=\"LibRaw\ 0.14.4\" -DPACKAGE_BUGREPORT=\"info#libraw.org\" -DPACKAGE_URL=\"http://www.libraw.org\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I. -I/usr/local/include -g -O2 -MT internal/dcraw_common.lo -MD -MP -MF $depbase.Tpo -c -o internal/dcraw_common.lo internal/dcraw_common.cpp &&\
mv -f $depbase.Tpo $depbase.Plo
libtool: compile: arm-linux-androideabi-g++ -DPACKAGE_NAME=\"LibRaw\" -DPACKAGE_TARNAME=\"libraw\" -DPACKAGE_VERSION=\"0.14.4\" "-DPACKAGE_STRING=\"LibRaw 0.14.4\"" -DPACKAGE_BUGREPORT=\"info#libraw.org\" -DPACKAGE_URL=\"http://www.libraw.org\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I. -I/usr/local/include -g -O2 -MT internal/dcraw_common.lo -MD -MP -MF internal/.deps/dcraw_common.Tpo -c internal/dcraw_common.cpp -fPIC -DPIC -o internal/.libs/dcraw_common.o
internal/dcraw_common.cpp: In member function 'void LibRaw::read_shorts(ushort*, int)':
internal/dcraw_common.cpp:119: error: 'swab' was not declared in this scope
internal/dcraw_common.cpp: In member function 'void LibRaw::write_ppm_tiff()':
internal/dcraw_common.cpp:9235: error: 'swab' was not declared in this scope
make: *** [internal/dcraw_common.lo] Error 1
I doubt this error message is helpfull here at stackoverflow, but I am left wondering if I should have applied some additional flags or configuration to get this to work?
Note that I am able to compile this lib succesfully if just compiling for my system without crosscompiling. (linux 32bit).
When I am looking to a instruction for building GDAL for Android (here), it uses a additional setting of LIBS="-lsupc++ -lstdc++". This links the STL and C++ exceptions?
However, when I set those before running my configure I get immediately errors like:
configure:3018: checking whether the C++ compiler works
configure:3040: arm-linux-androideabi-g++ conftest.cpp -lsupc++ -lstdc++ >&5
/tmp/android-chain/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: cannot find -lsupc++
collect2: ld returned 1 exit status
So, I am a bit stuck. Someone an idea?
I had to add an implementation of the swab function, since the NDK does not have that one.
Afterwards this compiled fine (but I used the crystax ndk).
A better way toolwise was to just use a Android.mk file and use ndk-build to compile it.
Linker error from the bottom of your question occurs because make-standalone-toolchain.sh from NDK r7 creates incomplete toolchain (it misses some libraries including libsupc++.a). I recommend you try making a toolchain from one of previous NDK releases (r6b should be fine).
Related
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 am trying to build boost_1.60.0 (as shared library) for android with c++11 support. I am using the latest ndk (currently android-ndk-r10e). The build host is Windows-10.
This is for a non-opensource project. So as far as I understand I cannot use gnustl_shared, and I need to use c++_shared as the android c++ runtime.
my project-config.jam looks like this:
androidNDKRoot = c:/android-ndk-r10e ;
using gcc : android :
$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ :
<root>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/
<compileflags>-MMD
<compileflags>-MP
<compileflags>-MF
<compileflags>-fpic
<compileflags>-ffunction-sections
<compileflags>-funwind-tables
<compileflags>-fstack-protector
<compileflags>-no-canonical-prefixes
<compileflags>-march=armv5te
<compileflags>-mtune=xscale
<compileflags>-msoft-float
<compileflags>-fno-rtti
<compileflags>-mthumb
<compileflags>-Os
<compileflags>-g
<compileflags>-DNDEBUG
<compileflags>-fomit-frame-pointer
<compileflags>-fno-strict-aliasing
<compileflags>-finline-limit=64
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/include
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../../android/support/include
<compileflags>-IC:/android-ndk-r10e/platforms/android-9/arch-arm/usr/include
<compileflags>-Wa,--noexecstack
<compileflags>-Wformat
<compileflags>-Werror=format-security
<compileflags>-DUNIX
<compileflags>-DANDROID
<compileflags>-Wl,--no-undefined
<cxxflags>-fexceptions
<linkflags>-lc++_shared
<archiver>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ar
<ranlib>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ranlib
;
the build command is:
b2 --toolset=gcc-android cxxflags="-std=c++11 " --prefix=..\boost_android_arm --builddir=./boost_android_arm/builddir target-os=linux --with-filesystem define=BOOST_FILESYSTEM_VERSION=3 link=shared runtime-link=shared threading=multi
In order to determine the parameters in the project-config.jam I've build a sample shared library using the ndk-build, get its debug messages, and extracted the compile and link commands it uses.
compile:
C:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe,C:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi/objs/someLib/./Unity1.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Ijni/../../library/../../../../ -Ijni/../../library/../../../../src/ -IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include -IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/include -IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../../android/support/include -Ijni/../../library -DANDROID -DHAVE_CONFIG_H -DSESTEK_ANDROID_XERCES_HACK -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -fno-strict-aliasing -frtti -fexceptions -DUNIX -DANDROID -IC:/android-ndk-r10e/platforms/android-9/arch-arm/usr/include -c jni/../../library/./Unity1.cpp -o ./obj/local/armeabi/objs/someLib/./Unity1.o,...)
link:
C:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe,C:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,-soname,libsomeLib.so -shared --sysroot=C:/android-ndk-r10e/platforms/android-9/arch-arm ./obj/local/armeabi/objs/someLib/./Unity1.o -lgcc ./obj/local/armeabi/libc++_shared.so -no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -mthumb -lc -lm -o ./obj/local/armeabi/libsomeLib.so,...)
For brevity I've only build filesystem for this trial but in the end I plan to build at least thread, filesystem, date_time, asio and log libraries.
Finally the error I get is as follows.
...patience...
...found 660 targets...
...updating 13 targets...
gcc.compile.c++ bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\error_code.o
gcc.link.dll bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\libboost_system-gcc-mt-1_60.so.1.60.0
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot open crtbegin_so.o: No such file or directory
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lrt
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot open crtend_so.o: No such file or directory
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lc++_shared
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lstdc++
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lm
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lc
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -ldl
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: cannot find -lc
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\error_code.o: requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\error_code.o: requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld.exe: error: bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\error_code.o: requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
./boost/system/detail/error_code.ipp:458: error: undefined reference to '__dso_handle'
./boost/system/detail/error_code.ipp:464: error: undefined reference to '__dso_handle'
./boost/system/detail/error_code.ipp:158: error: undefined reference to '__dso_handle'
collect2.exe: error: ld returned 1 exit status
"c:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++" -o "bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\libboost_system-gcc-mt-1_60.so.1.60.0" -shared -Wl,--start-group "bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\error_code.o" -Wl,-Bstatic -Wl,-Bdynamic -lrt -Wl,--end-group -lc++_shared -pthread
...failed gcc.link.dll bin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi\libboost_system-gcc-mt-1_60.so.1.60.0...
...skipped <pstage\lib>libboost_system-gcc-mt-1_60.so.1.60.0 for lack of <pbin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi>libboost_system-gcc-mt-1_60.so.1.60.0...
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\codecvt_error_category.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\operations.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\path.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\path_traits.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\portability.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\unique_path.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\utf8_codecvt_facet.o
gcc.compile.c++ bin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi\windows_file_codecvt.o
...skipped <pbin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi>libboost_filesystem-gcc-mt-1_60.so.1.60.0 for lack of <pbin.v2\libs\system\build\gcc-android\release\target-os-linux\threading-multi>libboost_system-gcc-mt-1_60.so.1.60.0...
...skipped <pstage\lib>libboost_filesystem-gcc-mt-1_60.so.1.60.0 for lack of <pbin.v2\libs\filesystem\build\gcc-android\release\target-os-linux\threading-multi>libboost_filesystem-gcc-mt-1_60.so.1.60.0...
...failed updating 1 target...
...skipped 3 targets...
...updated 9 targets...
The error tells that it needs the directory to find the necessary libraries, but the problem is that under android ndk there are several files with names rt and crtbegin_so.o and such. I guess I need to make the compiler determine the correct directory itself.
With all being said what I need actually is to build boost shared libraries for android with c++11 support. So I may accept your help either by pointing me in the right direction using the above build parameters or providing me a working sample so I can work out the details myself.
Oh also one more thing: if I use link=static instead of link=shared in the build command the build succeeds. But I have not tried the produced static libraries.
Building Boost on Linux using the NDK
I know you're asking about Windows, but I wanted to do this on macOS and it failed with nearly the exact error. I finally broke down and did it on my linode server it worked without a problem. This says to me that they aren't really doing a good job of testing other platforms. Compiling static only on macOS works as you also discovered on Windows.
Point of reference
NDK R13
Boost 1.62.0
Tested with clang++; g++ also works
If you're wondering why I'm using clang, the Release Notes have the following message:
GCC is no longer supported. It will not be removed from the NDK just
yet, but is no longer receiving backports. It cannot be removed until
after libc++ has become stable enough to be the default, as some parts
of gnustl are still incompatible with Clang. It will likely be removed
after that point.
user-config.jam
I placed this file in my home directory. Yuck.
androidNDKRoot = /path/to/ndk-R13-standalone ;
using clang : android
:
$(androidNDKRoot)/bin/arm-linux-androideabi-clang++
:
;
Modifying libtool.m4 in boost to avoid versioning of the libraries
libtool.m4 under tools/build/src/engine/boehm_gc/libtool.m4 in the boost source has no reference to android and you'll need to change version_type=linux in the section linux*) to version_type=none. This will cause symbolic links to appear without the version number appended to the end linked to the versioned shared libraries in the output.
Building
Target OS MUST be android to avoid the -lrt flag being passed which will cause shared linking to fail.
./b2 \
-d+2 \
-j 4 \
--reconfigure \
target-os=android \
toolset=clang-android \
include=${ANDROID_NDK_STANDALONE}/include/c++/4.9.x \
link=static,shared \
variant=debug,release \
threading=multi \
--layout=versioned \
--prefix=${BOOST_INSTALL_DIR} \
install
A relevant information is here (Boost for Android), where they have been able to successfully build the shared libraries, but it seems that the resulting files have a version suffix which android can't handle. Also one can't just rename the binary because the file name is hardcoded in it. One way out, as per the last post, is to set the variable version_type to none (version_type=none) in the linux section of file. In your case, the build setup could be a little different, but it may be worthwhile to take a look at the changes they made at that discussion.
user-config.jam
If you want to find boost from cmake(find_package) you must use the version of compiler, and not android like the top answer, in your user-config.jam like below according to boost doc.
androidNDKRoot = /path/to/ndk-R13-standalone ;
using clang : 8.0.1
:
$(androidNDKRoot)/bin/arm-linux-androideabi-clang++
:
;
My answer for me in future. How to build latest Boost(1.79.0) with latest NDK(24.0) on Windows PC for Android.
Go to your downloaded boost_1_79_0 unpacked directory and build b2 tool:
.\bootstrap.bat
Check b2 tools is ready:
b2 --version
B2 4.8-git <-- possible output
create file user-config.jam in %HOME% directory with content like that(example):
using clang : arm64 : c\:/Users/l_chayka/Downloads/android-ndk-r24/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang++.cmd : <cxxflags>-std=c++20 ;
using clang : arm : c\:/Users/l_chayka/Downloads/android-ndk-r24/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi21-clang++.cmd : <cxxflags>-std=c++20 ;
using clang : x86 : c\:/Users/l_chayka/Downloads/android-ndk-r24/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android21-clang++.cmd : <cxxflags>-std=c++20 ;
using clang : x86_64 : c\:/Users/l_chayka/Downloads/android-ndk-r24/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android21-clang++.cmd : <cxxflags>-std=c++20 ;
Go to boost root and try to build for every Android architecture (arm, arm64, x86, x86_64) example:
c:\Users\l_chayka\Downloads\boost_1_79_0>b2.exe toolset=clang-x86_64 target-os=android link=static variant=debug threading=multi --layout=versioned --prefix=c:/boost-x64_86/ install
c:\Users\l_chayka\Downloads\boost_1_79_0>b2.exe toolset=clang-x86 target-os=android link=static variant=debug threading=multi --layout=versioned --prefix=c:/boost-x86/ install
c:\Users\l_chayka\Downloads\boost_1_79_0>b2.exe toolset=clang-arm target-os=android link=static variant=debug threading=multi --layout=versioned --prefix=c:/boost-arm/ install
c:\Users\l_chayka\Downloads\boost_1_79_0>b2.exe toolset=clang-arm64 target-os=android link=static variant=debug threading=multi --layout=versioned --prefix=c:/boost-arm64/ install
Now check you instalation prefix path.
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 am trying to use the Android NDK on Mountain Lion to build a library for Android, following this guide
http://masl.cis.gvsu.edu/2012/01/25/android-echoprint/
When it comes time to compile the library, I run:
cd <path to jni>
<ndk>/ndk-build
I get the following error:
Compile++ thumb : echoprint-jni <= AndroidCodegen.cpp
arm-linux-androideabi-g++: error trying to exec 'cc1plus': execvp: No such file or directory
make: *** [/Users/wingdom/Desktop/obj/local/armeabi/objs/echoprint-jni/AndroidCodegen.o] Error 1
I believe I have added everything I need to to my path variable:
export PATH=$PATH:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:Developer/android-sdk/tools:/Developer/android-sdk/platform-tools:/Developer/android-ndk:/Developer/android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin
What else do I need to do in order to get this to compile? I am using the r8b NDK currently, but have tried it with versions all the way back to 6.
EDIT:
I tried this solution: Error while building android ndk sample project
adding
export PATH=$PATH:/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5.2
to my path gets me this error:
cc1plus: error: unrecognized command line option "-mbionic"
cc1plus: error: unrecognized command line option "-mthumb"
cc1plus: error: unrecognized command line option "-mfpu=vfp"
/Users/wingdom/Desktop/jni/AndroidCodegen.cpp:1: error: bad value (armv5te) for -march= switch
/Users/wingdom/Desktop/jni/AndroidCodegen.cpp:1: error: bad value (xscale) for -mtune= switch
make: *** [/Users/wingdom/Desktop/obj/local/armeabi/objs/echoprint-jni/AndroidCodegen.o] Error 1
but adding
export CROSS_COMPILER=$PATH:/Developer/android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin
doesn't help, like it did in the link above.
I have experienced same error.
I was not able to execute even 'gcc, g++' command. So I have googled a lot to find solution, but nothing helped for me.
Then, I found that some filename in ndk is not correct, with tailing _ on some filename.. (In my case, in toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/arm-linux-androideabi/bin folder, there are gcc_, g++_, c++_ instead of gcc, g++, c++.)
I used The unarchiver to extract NDK archive, so I think there are something wrong with unarchiving procedure.
So I re-downloaded NDK and checked MD5 checksum, then extracted archive using Mac's default archive utility.
Now, the problem has solved.
Sounds like you have a bad download/unpack of the NDK. The cc1plus binary that it's looking for should be in $NDK_HOME/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/libexec/gcc/arm-linux-androideabi/4.4.3/. If it's not there, try re-downloading the SDK and/or unpacking it again.
If it is there, be sure to build passing V=1 to ndk-build, and see if there are any odd -B options passed to the compiler. The -B option tells gcc where to find its "sub-programs" (of which cc1plus is one). Pretty sure there shouldn't be any on the command lines for r8, so if there are, something somewhere is passing bad flags. For example, on my system, a C++ NDK command line ends up looking something like this:
/opt/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi-v7a/objs/sometarget/SomeCppFile.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-exceptions -fno-rtti -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/opt/android-ndk/sources/cxx-stl/stlport/stlport -I/opt/android-ndk/sources/cxx-stl//gabi++/include -DANDROID -Wall -Wa,--noexecstack -frtti -O2 -DNDEBUG -g -I/opt/android-ndk/platforms/android-8/arch-arm/usr/include -c jni/SomeCppFile.cpp -o ./obj/local/armeabi-v7a/objs/sometarget/SomeCppFile.o
Maybe you need to install the g++:
$sudo apt-get install g++
I have spent about a day to find root cause of this
arm-linux-androideabi-gcc: error trying to exec 'cc1': execvp: No such file...
and others issues.
The issues were that I unpacked NDK and SDK with 7z which removed executable permission for all binaries and Eclipse was not able to start cc1.
Once I unpacked tar files of SDK and NDK using tar, everything started working well.
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.