Undefined Function outside Header Error Android NDK - android

I am currently linking a static library to my Android Project which contains the functions I want to use, the problem that occurs is when I call a function from the static library in Android Project, and the function definition is in a .cpp file, my build fails. If that function is defined in a header through a class for example, the project compiles and runs.
The .cpp file is compiled with the definition and the project still outputs an error of no definition.
Edit: I noticed a new error message of the function outputting that it's not an ELF object.
Android Project Calls Function from Static Library:
Example.h
void example();
Example.cpp
void example()
{
} //Error
Example.h
class example
{
public:
void example()
{
}//Compiles
}
Error:
"C:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin\ld" -z noexecstack --warn-shared-textrel -z now -z relro --hash-style=both --enable-new-dtags --eh-frame-hdr -m elf_i386 -shared -o "Debug\\Android-x86\\x86\\libProject.so" "C:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../sysroot/usr/lib/i686-linux-android/16\crtbegin_so.o" "-LC:\\ProjectFolder\\ProjectFolder\\Debug\\Android-x86\\x86" "-LC:\\ProjectFolder\\ProjectFolder\\StaticLibrary" "-LC:\\ProjectFolder\\ProjectFolder\\StaticLibrary\\Source" -u ANativeActivity_onCreate "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\lib64\clang\9.0.9\lib\linux\i386" "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../lib/gcc/i686-linux-android/4.9.x" "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../sysroot/usr/lib/i686-linux-android/16" "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../sysroot/usr/lib/i686-linux-android" "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/lib" "-LC:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../sysroot/usr/lib" --exclude-libs libgcc.a --exclude-libs libatomic.a -z noexecstack -z relro --build-id=md5 --no-undefined -z now "Debug\\Android-x86\\Main.o" -lEGL -lGLESv2 -landroid -latomic -lStaticLibrary "C:\\Users\\User\\AppData\\Local\\Android\\Sdk\\ndk\\21.4.7075529\\toolchains\\llvm\\prebuilt\\windows-x86_64\\sysroot\\usr\\lib\\i686-linux-android\\libc++_shared.so" -soname=libProject.so -lc++ -lm -lgcc -ldl -lc -lgcc -ldl "C:\Users\User\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin/../sysroot/usr/lib/i686-linux-android/16\crtend_so.o"
1>C:\ProjectFolder\ProjectFolder\ProjectFolder/Main.cpp(10): error : undefined reference to 'FunctionName()'
1>C:\ProjectFolder\ProjectFolder\ProjectFolder/Main.cpp(10): error : clang++: error: linker command failed with exit code 1

The linker clearly says undefined reference to 'FunctionName()'
In other words it can't find the source file with FunctionName() implementation. Make sure the file is compiled or implementation is placed in the same namespace with the same name (in this particular case without any namespace).

I tried moving all my static library files to a new project and it seems that the previous static library Visual Studio project was corrupted, after moving over to a new clean project everything compiled.

Related

Unable to run dynamically cross compiled application on arm device [duplicate]

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.

Error during Cross-compiling C code with Dynamic libraries

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.

NDK: libm static linking

I have a problem during try to compile sources with recent android-9 x86 platform.
Primary question: why static library libm.a and dynamic libm.so are different?
Problem is i've try to compile:
/path/to/android-ndk-r8/toolchains/x86-4.4.3/prebuilt/linux-x86/bin/i686-android-linux-gcc --sysroot=/path/to/android-ndk-r8/platforms/android-9/arch-x86 -I/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/include -I/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/libs/x86/include -L/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/lib -L/path/to/android-ndk-r8/platforms/android-9/arch-x86/usr/lib -static /path/to/gcc_4_4_6_release/gcc/testsuite/gcc.dg/complex-5.c -std=c99 -O -ffloat-store -o ./complex-5.exe -lm
but I have undefined reference:
/tmp/cc78CsCp.o: In function main': complex-5.c:(.text+0x1a2):
undefined reference tofeclearexcept' complex-5.c:(.text+0x1b3):
undefined reference to `fetestexcept' collect2: ld returned 1 exit
status
pwd: /path/to/android-ndk-r8/platforms/android-9/arch-x86/usr/lib
ls libm*
libm.a libm.so
It exists, but if we look with nm for feclearexcept, it isn't present within static library.
Ok, just try to remove -static flag.
/path/to/android-ndk-r8/toolchains/x86-4.4.3/prebuilt/linux-x86/bin/i686-android-linux-gcc --sysroot=/path/to/android-ndk-r8/platforms/android-9/arch-x86 -I/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/include -I/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/libs/x86/include -L/path/to/android-ndk-r8/sources/cxx-stl/gnu-libstdc++/lib -L/path/to/android-ndk-r8/platforms/android-9/arch-x86/usr/lib /path/to/gcc_4_4_6_release/gcc/testsuite/gcc.dg/complex-5.c -std=c99 -O -ffloat-store -o ./complex-5.exe -lm
Ok. That the question: why they are differ? I need static linkage, I don't want to force usage of dynamic linkage with -Wl,-Bdynamic -lm. By the way: regular linux libm.a and libm.so contains similar list of functions.

android GMP cross compilation

I'm on debian/amd64 and I want to cross-compile GMP for android 2.2 using NDK-7b. I took the source code from [gmplib](hg clone http://gmplib.org:8000/gmp-5.0 gmp).
I configured it with:
./configure --enable-shared --host=arm-linux-androideabi --prefix=/home/fabien/android/spica/ndk-standalone-8 CFLAGS="-v -march=armv5te -mtune=xscale -msoft-float -Wl,-rpath,lib/ -DANDROID -ffunction-sections -funwind-tables -fstack-protector -funswitch-loops -finline-limit=300 -Wall -O3 -nodefaultlibs -fPIC -shared -Wl,--no-allow-shlib-undefined" PKG_CONFIG_PATH="/home/fabien/android/spica/ndk-standalone-8/lib/pkgconfig" LDFLAGS="-Wl,-rpath-link -Wl,/home/fabien/android/spica/ndk-standalone-8/lib -L/home/fabien/android/spica/ndk-standalone-8/lib"
I modified the file config.h by setting:
/* Define to 1 if you have the `obstack_vprintf' function. */
#ifndef ANDROID
#define HAVE_OBSTACK_VPRINTF 1
#endif
/* Define to 1 if you have the `localeconv' function. */
#ifndef ANDROID
#define HAVE_LOCALECONV 1
#endif
/* Define to 1 if you have the `vsnprintf' function and it works properly. */
#ifndef ANDROID
#define HAVE_VSNPRINTF 1
#endif
I updated the SUBDIRS parameter as follows in Makefile:
SUBDIRS = tests mpn mpz mpq mpf printf scanf cxx mpbsd demos tune
It seems to compile when I run make:
libtool: link: (cd ".libs" && rm -f "libgmp.so" && ln -s "libgmp.so.10.0.5" "libgmp.so")
libtool: link: ( cd ".libs" && rm -f "libgmp.la" && ln -s "../libgmp.la" "libgmp.la" )
But when I run "make check", the linker seems lost:
/../../../../arm-linux-androideabi/bin/ld: warning: ld-linux.so.3, needed by /home/fabien/android/spica/sources/gmp/.libs/libgmp.so, not found (try using -rpath or -rpath-link)
t-bswap.o:(.ARM.exidx.text.main+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
./.libs/libtests.a(misc.o):(.ARM.exidx.text.align_pointer+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
.
.
.
refmpn.c:(.text.refmpn_get_str+0xb8): undefined reference to `__aeabi_uidiv'
refmpn.c:(.text.refmpn_get_str+0x238): undefined reference to `__aeabi_ui2d'
refmpn.c:(.text.refmpn_get_str+0x250): undefined reference to `__aeabi_dmul'
refmpn.c:(.text.refmpn_get_str+0x254): undefined reference to `__aeabi_d2uiz'
./.libs/libtests.a(refmpn.o):(.ARM.exidx.text.refmpn_get_str+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
/home/fabien/android/spica/sources/gmp/.libs/libgmp.so: undefined reference to `abort#GLIBC_2.4'
/home/fabien/android/spica/sources/gmp/.libs/libgmp.so: undefined reference to `puts#GLIBC_2.4'
Any hints ?
This error is due to the fact that the file that contains these helper functions (these are GCC helper functions) is not being included when the linker creates the target. To fix this, please add the libgcc.a (which contains the GCC helper function definitions) into the linker flags.
As for the location of libgcc.a, assuming gcc version arm-linux-androideabi-4.4.3, it will be
$NDK_ROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a
This will NOT fix the following errors(which seem to be related to the GNU libc being missing):
.libs/libgmp.so: undefined reference to `abort#GLIBC_2.4'
.libs/libgmp.so: undefined reference to `puts#GLIBC_2.4'
The above 2 errors will always show up as android uses the Bionic libc, and not the GNU libc
Note: This method will fix similar issues on all systems, not just Android.

Building native library with standalone toolchain android arm

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).

Categories

Resources