Linker can't find function - android

Im trying to build an Ubuntu Touch tree, based on an Aosp tree I already correctly built.
It fails with this error
CAPEWrapper.cpp:16: error: undefined reference to '__xlog_buf_printf'
this is the header that file includes
#include "CAPEWrapper.h"
which on cascade includes
#include <cutils/xlog.h>
which in turn defines
#if defined(__cplusplus)
extern "C" {
#endif
int __xlog_buf_printf(int bufid, const struct xlog_record *rec, ...);
#if defined(__cplusplus)
}
#endif
I suspect that my g++ doesn't set __cplusplus macro. Could it be a realistic scenario with this kind of error? If this could be the problem, should I need to specify a standard implementation with "stdc=something" to solve it?
Any other idea is welcome.

Make sure that your project is linking libcutils, and that it's linking it in the correct order (i.e. that -lcutils appears in the linker command line after any module that depends on it).

In the end, I found that the modules was listed inside a macro called LOCAL_WHOLE_STATIC_LIBRARIES, that in Android environment passes its content to the --whole-archive flag of GCC linker.

Related

Building an Android executable gRPC server that uses protocol buffers (without APK)

I compiled the gRPC Android example from here.
I want to run the program as executable from adb shell.
Added these lines to grpc-helloworld.cc:
#include <iostream>
int main() {
std::cout << "qwerty" << std::endl;
return 0;
}
And these lines to its CMakeLists.txt:
add_executable(avocado
src/main/cpp/grpc-helloworld.cc)
target_include_directories(avocado
PRIVATE ${HELLOWORLD_PROTO_HEADERS})
target_link_libraries(avocado
helloworld_proto_lib
android
${log-lib})
Then I pushed the generated executable and libs file and tried to run it:
LD_LIBRARY_PATH=. ./avocado
I got the following error:
[libprotobuf FATAL
/home/buga/grpc/third_party/protobuf/src/google/protobuf/stubs/common.cc:79]
This program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)terminating
with uncaught exception of type google::protobuf::FatalException: This
program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)
Aborted
What am I doing wrong?
We realized that there is a version of the protobuf library called libprotobuf-cpp-full.so and libprotobuf-cpp-lite.so, and it seems that their version is 3.0.0. This is conflicting with our version (3.5.1) which is compiled into either a static lib, or as a shared lib.
I'm not quite sure why this happens. Something about once the linker loads helloworld_proto_lib, it overrides all loaded protobuf symbols, and for some reason another library that you had nothing to do with crashes your program. But that's not telling you anything new.
Here's one way to solve this problem:
1. Changes to grpc-helloworld.cc
Make the main extern "C", and change its name maybe. For example:
extern "C" int my_main() {
std::cout << "qwerty" << std::endl;
return 0;
}
2. Add file grpc-avocado.cc
This will contain the actual main of the executable, which will dynamically load the libraries helloworld_proto_lib and grpc-helloworld. Here's how to do it:
#include <iostream>
#include <android/dlext.h>
#include <dlfcn.h>
int main() {
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
void* proto_lib = android_dlopen_ext("/path/to/libhelloworld_proto_lib.so", RTLD_LAZY, &extinfo);
void* helloworld = dlopen("/path/to/libgrpc-helloworld.so", RTLD_LAZY);
int (*my_main)() = (int (*)())dlsym(helloworld, "my_main");
return my_main();
}
The function android_dlopen_ext from #include <android/dlext.h>, and its flag argument, are described here: https://developer.android.com/ndk/reference/group/libdl . In the above code we pass the flag ANDROID_DLEXT_FORCE_LOAD, which is documented as:
When set, do not use stat(2) to check if the library has already been loaded.
This flag allows forced loading of the library in the case when for some reason multiple ELF files share the same filename (because the already-loaded library has been removed and overwritten, for example).
Note that if the library has the same DT_SONAME as an old one and some other library has the soname in its DT_NEEDED list, the first one will be used to resolve any dependencies.
I think the text in bold is what explains why this solution works.
3. Change CMakeLists.txt
Since you'll be loading helloworld_proto_lib dynamically, you can now remove it from the executable definition, and there's no need for any proto headers:
add_executable(avocado
src/main/cpp/grpc-avocado.cc)
target_link_libraries(avocado
android
${log-lib})
Build, push, and run
You can now build, push the executable avocado and the two libraries libgrpc-helloworld.so, libhelloworld_proto_lib.so, and run. You don't need LD_LIBRARY_PATH. Good luck with the rest of your project!

Android NDK CMake linking issues

I'm quite new with NDK + Gradle + CMake integration and I'm trying to understand why linking doesn't export symbols as intended.
I have a static library built by a CMakeLists.txt which is not the main CMakeLists.txt.
The scripts does something like:
# main CMakeLists.txt
add_subdirectory(${LIBS}/foo libs}
add_library(native SHARED native.cpp)
# omitting standard android libraries
target_link_libraries(native foo ${android-lib} ${log-lib})
while CMakeLists.txt inside ${libs}/foo is the following:
# misc configuration of ${SRC}
add_library(foo STATIC ${SRC})
The script works fine, it's able to link libnative.so and I'm able to find the generated libfoo.a. Everything seems fine.
I then try to define a native method in foo.cpp contained in foo library:
extern "C" JNIEXPORT void JNICALL Java_com_mypackage_Controls_onTap(JNIEnv*, jobject, int x, int y) {
// log something
}
But I'm not able to call the native method defined in foo library. I get an UnsatisfiedLinkError at runtime. If, instead, I move (directly by copying and pasting) the method to native.cpp then everything goes fine.
So basically:
Java -> method in native.cpp works
Java -> method in native.cpp -> method defined in foo library works
Java -> method in foo library doesn't work (UnsatisfiedLinkError)
I tried to inspect the exported functions with nm and it looks like that foo.a correctly exports the native function as I can see
00011060 T Java_com_mypackage_Controls_onTap
But this entry disappears from libnative.so. If, instead, I define the method directly in native.cpp then I can see it correctly with nm also on libnative.so.
In addition calling any method in foo library from native.cpp works as intended so the library is effectively statically linked.
I am not able to understand the reason behind this, the approach should be fine, visibility should be correct as specified by JNIEXPORT macro so I'm really groping in the dark (and Gradle doesn't provide any output of compilation phase so I can't understand what's happening, but the build.ninja file seems correct)
This behavior, even if unpleasant, is correct. The linker drops any object "files" (in your case, foo.o) from used static libraries, unless they are "pinned" by one of the objects in the shared lib (in your case, native.o). There are three ways to solve the problem:
compile foo.cpp as part of libnative.so instead of a
static lib.
reference Java_com_mypackage_Controls_onTap or any other
external symbol from foo.cpp in native.cpp
use SET(native -Wl,--whole-archive foo -Wl,--no-whole-archive) (see https://stackoverflow.com/a/17477559/192373)

Android NDK compiling C++ code gets a Type 'errno_t' could not be resolved

I'm compiling C++ code written primarily for Mac OS, using the Android NDK and I get the following error:
- Type 'errno_t' could not be resolved
In Xcode this type is defined on OSX 10.0/usr/include/sys/_types/_errno_t.h as this:
#ifndef _ERRNO_T
#define _ERRNO_T
typedef int errno_t;
#endif /* _ERRNO_T */
Any suggestions on how to convert this to the NDK, or add compiler flags to make this compile, or where to even get the source code to define this type in my source code itself?
Thanks.
See this answer for information on errno_t.
errno_t is not a part of the C standard, and bionic doesn't support it.
The fix is simply to change all the errno_ts to be ints.

What this error means and how to solve it?

I am trying to build a C++ code using NDK in android. I have a method which has a parameter vector < vector <float> > coordinates
Everything builds fine until I write this line inside my method
vector<float> firstPoint = coordinates.at(0);
I start getting this error
D:/eclipseworkspace/myLibProject/obj/local/armeabi/libmyLibProject.a(FileName.o): In function `std::priv::_Vector_base<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::_M_throw_out_of_range() const':
D:/androidndk/sources/cxx-stl/stlport/stlport/stl/_vector.c:45: undefined reference to `std::__stl_throw_out_of_range(char const*)'
collect2: ld returned 1 exit status
make: *** [/cygdrive/d/eclipseworkspace/myLibProject/obj/local/armeabi/libOutputName.so] Error 1
I have no clue why this is happening and Google is not helping either.
Thanks.
I think you are using two different implementation of the standard library in the same project.
It looks like you are compiling your files with (the headers of) an stlport implementation of the standard library in D:/android..., and you link against your local library.
You have to configure the linker in your ide (or Makefile) to use also the lib file of the same implementation (somewhere in D:/android... I guess).
This is a linking error. You need to add APP_STL := stlport_static to your Apllication.mk file. Also make sure that you use -fno-exceptions flag, since STLport is not compatible with C++ exceptions and RTTI.
You can get more info in APPLICATION-MK.HTML which is availavle in the docs folder of the NDK. CPLUSPLUS-SUPPORT.HTML is also worth to read.
this looks like a linker error. You probably forgot to add STL library reference to your build. Or it can't be found
Did you do this ?
#include <stdexcept>
#include <vector>
using namespace std;
When I changed
vector<float> firstPoint = coordinates.at(0);
to
vector<float> firstPoint = coordinates[0];
it started compiling..... :s y?

Problem to build NDK with C++ in Android

Currently I am working with the Android NDK and JNI. I am trying to build a C++ code with NDK.
But I got the following errors:
E:/Android/Tranining_workspace/BackUpMigrant/jni/ReadBackupArc5/ReadBackupArc5.cpp:10:19: error: fstream: No such file or directory
E:/Android/Tranining_workspace/BackUpMigrant/jni/ReadBackupArc5/ReadBackupArc5.cpp:20: error: 'ifstream' does not name a type
E:/Android/Tranining_workspace/BackUpMigrant/jni/ReadBackupArc5/ReadBackupArc5.cpp:21: error: 'ofstream' does not name a type
E:/Android/Tranining_workspace/BackUpMigrant/jni/ReadBackupArc5/ReadBackupArc5.cpp:22: error: 'ofstream' does not name a type
E:/Android/Tranining_workspace/BackUpMigrant/jni/ReadBackupArc5/ReadBackupArc5.cpp:34: error: 'string' was not declared in this scope
Can anyone please help me out?
I just encountered the same problem. Seems the STL is not automatically included in NDK projects by default. That also means iostream, fstream, string etc can't be used straight away. To enable them, you'll need to modify your Application.mk file. If you don't have one (it's in the <project>/jni directory), then just create a new, blank one. Add the line:
APP_STL := stlport_static
Also, also remember to include using namespace std; or equivalent, along with the usual #include <iostream> etc.
Did you remember your:
#include <iostream>
using namespace std;
definitions at the top of the file?
("using namespace std" isn't always a good idea, but that's a separate issue.)

Categories

Resources