I compile my Android NDK library with -fshort-wchar. I know the RTL assumes 4-byte wchar_t, I know what I'm doing, the library works. However, on every build linker gives me the following warning for every object file:
ld.exe: warning: MyFile.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
When I provide
LOCAL_LDLIBS := --no-wchar-size-warning
This gives me an "unrecognized option" error.
Adding APP_LDFLAGS += -Wl,--no-wchar-size-warning (to Application.mk) works fine for me on NDKs at least as early as r7.
I assume it would work just the same as:
LOCAL_LDLIBS := -Wl,--no-wchar-size-warning
Have you seen this? The post explains that the --no-wchar-size-warning option will make the linker treat the mismatch as a warning, not an error. As in the enum case, the authors choose to display the message anyway.
You don't see the effect of setting this flag in your project because as detailed elsewhere, using -fshort-wchar automatically adds -Wl,--no-wchar-size-warning.
Related
I'm trying to get an instance to Android's sensor manager through the NDK.
To do this, I use the following function:
ASensorManager* manager = ASensorManager_getInstanceForPackage(PACKAGE_NAME);
When compiling I notice that the linker fails, complaining that there is an undefined reference.
error: undefined reference to 'ASensorManager_getInstanceForPackage'
This occurred very much to my surprise, since after looking at NDK header file located at
ndk-bundle\sysroot\usr\include\android\sensor.h, I saw that the function was indeed present.
So, believing that perhaps I was targeting an older version of the Android NDK, I attempt to use the now-deprecated function to obtain an instance:
ASensorManager* manager = ASensorManager_getInstance();
Again to my surprise, this failed as well! Instead, the compiler complains that the function is deprecated.
C:/Users/Nicholas/AppData/Local/Android/sdk/ndk-bundle/build//../sysroot/usr/include\android/sensor.h:384:17: note:
'ASensorManager_getInstance' has been explicitly marked deprecated here
__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
Even more alarming is that the compiler referenced the same sensor.h header as before and couldn't find the first function.
Why can't either function be used to obtain an instance of the sensor manager?
Necessary targeting information:
build.gradle
compileSdkVersion 24
buildToolsVersion '25.0.0'
AndroidManifest.xml
android:minSdkVersion="24"
android:targetSdkVersion="24"
Android.mk
As far as I can tell, there are no additional libraries that need to be referenced in order to use sensor.h, but regardless, I've included the relevant section of the Android.mk file:
LOCAL_LDLIBS := -llog -landroid -lGLESv3 -lEGL
ASensorManager_getInstanceForPackage requires API >= 26. Check at the bottom of its documentation description.
In case still doesn't work, there was a reported issue, although seems to be fixed already:
https://issuetracker.google.com/issues/37324654#c1
I am seeing a very strange failure that is very similar to the problem described in
dynamic_cast on llvm clang compiler failing: dynamic_cast returns nullptr when I am trying to downcast from base type to derived type, for an object of derived type. In my case though typeid actually shows the same dynamic type.
Below is the debug function that I use to verify run-time types. It takes a pointer of SrcType* and tries to dynamically cast it to pointer of DstType*. If conversion fails, i.e. the returned pointer is nullptr, it prints an error message. VERIFY() macro checks if condition is true:
template<typename DstType, typename SrcType>
void CheckDynamicType( SrcType *pSrcPtr )
{
VERIFY(dynamic_cast<DstType*> (pSrcPtr) != nullptr,
"Dynamic type cast failed. Src typeid: \'", typeid(*pSrcPtr).name(),
"\' Dst typeid: \'", typeid(DstType).name(), '\'');
}
And here is the output that I am getting:
Dynamic type cast failed. Src typeid: 'N8Diligent15RefCountersImplE' Dst typeid: 'N8Diligent15RefCountersImplE'
I am using clang compiler from Android ndk r16 toolchain. I am compiling with rtti flag. The same code works fine on gcc and msvc.
Another bit of information: the code also works fine if I build it with gnustl runtime (I am not sure how gnu stl works with clang, but anyway).
UPDATE
After spending few more hours looking into the issue I found out that dynamic_cast fails when it is used on the object created in another module.
From this
Using clang++, -fvisibility=hidden, and typeinfo, and type-erasure and this posts it looks like dynamic_cast should work if the class is labeled with __attribute__((visibility("default"))) so that typeid structures from two modules will be merged. This, however does not help either and I am still seeing the issue.
If you’re using the stock system compiler there’s a near 0 chance dynamic_cast of the compiler isn’t working. This is tested and used extensively in everything from system software up.
I often read that Android kernel modules have to be compiled with -fno-pic to work. Is this specific to the ARM architecture, or why don't/(when do) kernel modules for x86 need to be compiled with that flag?
According to https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Code-Gen-Options.html, -fno-pic is the negative form of the -fpic parameter. From the same link:
-fpic Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code
accesses all constant addresses through a global offset table (GOT).
The dynamic loader resolves the GOT entries when the program starts
(the dynamic loader is not part of GCC; it is part of the operating
system). If the GOT size for the linked executable exceeds a
machine-specific maximum size, you get an error message from the
linker indicating that -fpic does not work; in that case, recompile
with -fPIC instead. (These maximums are 8k on the SPARC, 28k on
AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit.)
Position-independent code requires special support, and therefore
works only on certain machines. For the x86, GCC supports PIC for
System V but not for the Sun 386i. Code generated for the IBM RS/6000
is always position-independent.
When this flag is set, the macros __pic__ and __PIC__ are defined to
1.
So -fno-pic means something like "Do not use position-independent code (PIC)."
But why?
Well, by looking at https://developer.arm.com/products/software-development-tools/hpc/documentation/note-about-building-position-independent-code-pic-on-aarch64, we find that:
Using the -fpic compiler flag with GCC compilers on AArch64 causes the
compiler to generate one less instruction per address computation in
the code, and can provide code size and performance benefits. However,
it also sets a limit of 32k for the Global Offset Table (GOT), and the
build can fail at the executable linking stage because the GOT
overflows.
So, in the end, it seems like -fno-pic is more of a precaution than a real need. This, of course, is a guess and there might be more things involved.
I am building an Android app that loads in 2 native shared libraries at runtime: 1 that was built with an unresolved symbol in it and the other which resolves and defines that symbol. In Java, I load the shared library that defines the symbol first, then load the library that has the symbol declared as unresolved, and at this point, the runtime fails with:
"Cannot load library: reloc_library[]: 33 cannot locate 'someMethod'
So here's the one unique difference. The shared library with the undefined symbol obviously doesn't know about the shared library with the definition for the symbol in it.
I just assumed that if I loaded the library with the definition of the method first that when I loaded the 2nd library that called the method, it would be able to find it. Am I wrong on that? It seems in my case, an explicit dependency HAS to be compiled in between the two native libs, which means (I think) making .so's with unresolved symbols is useless.
I have searched vigorously for a similar issue with no luck. I think my problem is due to an architectural limitation, and I am considering approaching it a couple of other ways, but I would like to know if it can be fixed simply.
To be sure it wasn't some complexity of the library itself, I created two very simple C files:
fcn_defined.c:
int someMethod()
{
return 1;
}
fcn_undefined.c:
extern int someMethod();
int someOtherMethod()
{
someMethod();
}
Then build two shared objects where the fcn_undefined.c code creates a .so with someMethod still undefined and fcn_defined.c builds a .so with someMethod defined:
gcc -o libfcn_undefined.so fcn_undefined.c -shared -Wl,--export-dynamic
gcc -o libfcn_defined.so fcn_defined.c -shared -Wl,--export-dynamic
Doing a nm on these produces:
libfcn_undefined.so:
0001f08 d _DYNAMIC
00001fe8 d _GLOBAL_OFFSET_TABLE_
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002000 d __dso_handle
00000290 t __on_dlclose
00002004 A _edata
00002004 A _end
000002a0 t atexit
000002b4 T someOtherMethod
U someMethod
and libfcn_defined.so:
00001f0c d _DYNAMIC
00001fec d _GLOBAL_OFFSET_TABLE_
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002000 d __dso_handle
0000025c t __on_dlclose
00002004 A _edata
00002004 A _end
0000026c t atexit
00000280 T someMethod
So you can see someMethod() is defined in libfcn_defined.so (and it appears in the read elf dynsym section) and is undefined in the other lib.
If anyone is interested in the readelf output, I can add that as well.
In the Java side, I have a simple button in the emulator that I click, and it creates a class with the following in it:
static
{
System.loadLibrary("fcn_defined");
System.loadLibrary("fcn_undefined");
}
Just out of curiosity, I added a "-lfcn_defined" to the fcn_undefined compile line, and compared the nm and readelf outputs. the only difference in nm was that the "T someOtherMethod" started a few bytes further out and the readelf difference was the "NEEDED" line for fcn_defined. That's pretty much about what I expected. And it doesn't crash like this.
That's pretty much the full explanation. I did find some details about how Android forces you to load your libraries in reverse dependency order in Java, because it has (rather it had, has been fixed in API 18) no reference to your app's lib path in the LD_LIBRARY_PATH envvar. Unfortunately, I am requiring a minimum API lvl 10 to be able to use my app because of the market penetration, and secondly I tried API 19 anyway, and it still fails.
If I had to guess, I believe Android just doesn't support finding a symbol if you haven't explicitly told it to look at library X for the symbol. In other words, because I didn't build the library fcn_undefined with an explicit dependency on libfcn_defined.so, Android can't resolve it. Does anyone know if this is a bug or by design? Is this normal? It seems like you wouldn't have the option to create a .so with unresolved symbols if this was the case, and even funnier is that the Android NDK toolchain I'm using to build this has this feature on by default when you use ld (it doesn't complain about unresolved), and I tried turning the feature off but didn't seem to do anything, no warnings or errors generating the library.
So you may ask why I don't just compile the fcn_undefined library with a dependency on the fcn_defined library. Well that gets into a much bigger architectural discussion. The code I'm working with (fcn_undefined.c in this example) is a python extension built with a cross compiled python toolchain for ARM, and I'm calling this library from an NDK library, so now the NDK library depends on the python module which has an unresolved method in Python, which is defined in a static lib. Linking the static lib into the NDK shared lib means that I can't load the native shared libs in the correct order in Java (due to the issue mentioned previously that they fixed in API 18). I'm trying to work with the existing system since a team of others use it, and it is used to build for many platforms. sigh I clearly have other things to figure out, but I was hoping to nail the one above down at least.
The behavior you so beautifully demonstrated is by design (or lack of, if you will). You are right in part, the crazy_linker does resolve some of such issues (but not all of them). There is an easy but ugly workaround. Build a dummy libfcn_defined.so which only has T someMethod in its nm. Use it to link libfnc_undefined.so, using LD_LIBS. NDK will show a warning, but that's OK. LAoad the real libfcn_defined.so in your Java.
By Unix/ELF design, you need a NEEDED entry in libfnc_undefined.so that lists libfnc_defines.so as a dependency for the dynamic linker to look into it for missing symbols.
I.e. you should ensure that -lfcn_defined (or /path/to/libfcn_defined.so) appears in the link command that generated libfcn_undefined.so.
If you use ndk-build to generate both libraries, just list libfcn_defined.so as a LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES entry for libfcn_undefined.so.
If you use another build system, adapt accordingly.
I am porting to SDL2 and the Android platform a C++ game that uses SDL 1.2. Everything went well so far except for one thing: when I try to access the fields of SDL_Window, the compiler tells me
error: invalid use of incomplete type 'SDL_Window {aka struct SDL_Window}'
I think my installation of SDL may be faulty. I have compiled SDL 2.0.0 from the source found on libsdl.org using the folloing command:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-18
Then, I have copied the freshly built libSDL2.so into $ANDROID_TOOLCHAIN/sysroot/usr/lib and the files in the include/ directory in $ANDROID_TOOLCHAIN/sysroot/usr/include/SDL. These files are given to CMake and referenced by the game's code. I managed to convert every SDL calls and now I am stuck with this SDL_Window problem.
I did a quick search in SDL's source code and found that SDL.h includes SDL_video.h which contains a typedef SDL_Window on struct SDL_Window. Then I searched for this struct and did not find anything except in the original source archive, in a file named src/video/SDL_sysvideo.h. Since it is not a file of the API, I doubt I have to include it in my code.
So, how to find a definition of SDL_Window in SDL2, for Android (if this is relevant)?
It appears that the problem is a lack of knowledge of SDL 2's API. Let's remember that one does not access the fields of struct SDL_Window: there are functions to get the size and the flags of the window, such as SDL_GetWindowFlags and SDL_GetWindowSize.
So the problem is absolutely not related to the installation of the SDL or to Android builds. Sorry for the waste of time, people of the Web.
I would expect that you are expected to only deal in pointers to SDL_Window objects, and not actually put a full SDL_Window object on the stack.