-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
undefined reference with ndk r12 #126
Comments
Looks like you are targeting 24 but running on previous version of android. |
Yes, I was about to write the solution, I am using targetSdkVersion=24 on a lower device. |
I reopen to have more feedback: With (compileSdkVersion=24, targetSdkVersion=23), it runs. According to: I should be able to bump "targetSdkVersion" to 24, but it fails to run because of undefined reference (at least "__aeabi_memclr4"). Doesn't seem to be an API thing, but more low level library issue ? Signification of {min,max,target, compile}SdkVersion is quite blur ... (for years) |
Also happens to us, but only for armeabi-v7a target on some devices (HTC One M8, Android 6.0; SGS5; Android 6.0). It is weird that it does not happen on SGS4, Android 5.0.1 nor on Huawei P8Lite, Android 5.0.1. It also does not happen on arm64-v8a on SGS6, Android 6.0. |
Confirmed that setting |
Where are these functions defined?
finds nothing. |
I think there is confusion between targetSdkVersion and LOCAL_SDK_VERSION NDK interpretation of LOCAL_SDK_VERSION is minimum SDK version - which means that it is not guaranteed to work on devices with sdk < LOCAL_SDK_VERSION. I am not sure how targetSdkVersion gets propagated to LOCAL_SDK_VERSION - do you use gradle to build native libraries? (You are getting this error because if LOCAL_SDK_VERSION is set to 24 these symbols get LIBC_N version. These symbols were mistakenly versioned as LIBC_PRIVATE instead of LIBC in android-23 which was fixed in 24, hence the symbol version mismatch if you try to run load the library linked against libc.so from android-24 on android-23) |
@DoDoENT Then, calling targetSdkVersion 24: targetSdkVersion 23: I use gradle, but with some ndk commands so that it seems equivalent to calling ndk-build My build.gradle contains AndroidManifest.xml, my minSdkVersion is 10. According to : https://developer.android.com/guide/topics/manifest/uses-sdk-element.htm android:targetSdkVersion An integer designating the API Level that the application targets. If not set, the default value equals that given to minSdkVersion. This attribute informs the system that you have tested against the target version and the system should not enable any compatibility behaviors to maintain your app's forward-compatibility with the target version. The application is still able to run on older versions (down to minSdkVersion). |
@1bsyl, I was referring to APP_PLATFORM NDK parameter - it has to be set to |
In fact, the safest, is to set APP_PLATFORM to the minSdkLevel ? |
@1bsyl indeed, unless you need to use some NDK features available only in later API levels (like for example GLES3 on compatible devices, while falling back to GLES2 on older devices - in order to access GLES3 headers, you need APP_PLATFORM=android-21 or later, which produces binary which is not so compatible with KitKat and earlier Android versions). |
@DoDoENT And, bumping targetSdkVersion to 24 in build.gradle and AndroidManifest.xml, can it have some bad side effect ? (while keeping a lower APP_PLATFORM for the ndk side). |
@1bsyl from our experience at MicroBlink we recommend having compileSdkVersion always set to latest stable API level (currently this is 24), targetSdkVersion set to latest API level with which you have extensively tested your app (for us this is still 23, as we cannot test with 24 because Android N is still not released - bugs and failures on preview versions can be attributed to both bugs in your app as well as bugs in platform itself - this is why we usually wait for Google to release official build of new Android version and then we test on it) and minSdkVersion set to minimum API level your app supports (for us this is still 10 :-( ). One example where you may put your targetSdkVersion to 21, while using compileSdkVersion on 24 would be case when you have not implemented Android M permission model in your app. Similarly, if you have not prepared your app to work in multi-window environment introduced in Android N (will it be called Nutella?) you should not set targetSdkVersion to 24 (setting it so would mean that you have tested your app in multi window environment and this feature will be enabled for your app on devices running Android N). On NDK side, you should set APP_PLATFORM to same as minSdkVersion in build.grade to be absolutely sure your app will work correctly. However, if you need NDK features that were introduced in later API levels, you should set APP_PLATFORM to minimum API level which gives a feature you need and then test intensively on lower API levels to ensure everything works (this may require some weird hacks to ensure binary built with APP_PLATFORM=android-23 to work on Gingerbread :-P ). |
@DoDoENT: Just to confirm, the reason you can do this with GL is because you're not actually linking against any symbols introduced in android-21, but using If that's the case then we'll actually have a solution for you fairly soon (if not r13 than r14). We're working on unifying our headers so there's only one version of the headers for every API level, and things that need to be guarded by API level will just have the appropriate attributes/ifdefs to hide them as needed. All the GL constants could be exposed for every platform level though. See #120. |
As for the main bug here, as @dimitry- says, it looks like you're trying to run below your minimum platform version. Nothing we can do to fix that problem without a time machine :) |
@DoDoENT @DanAlbert In fact, it's not failing because of a missing function as reported initially. In both case, "__aeabi_memclr4" function is needed. As @dimitry- said, in the new android-24 version, the symbol get marked as "LIBC_N", and the issue is that the loader will fail to find this function on an older platform (eg android-23). Just emphasize the use-case that will be - in the future - problematic: If a new set of API appears (an extension of GLES3 for instance) and you want to use it, you can choose to bump the app_platform, and use the same trick of dlopen+fallback. But for now on, it will fail on older platform, because of the LIBC_N symbols. I think that's going to be the issue ... |
Exactly. We use android-21 headers because they define constants like EGL_OPENGL_ES3_BIT and GL_UNPACK_ROW_LENGTH and function glPixelStorei which is the only function we currently use that is specific to GLES3 - those all are defined in GLES3/gl3.h which does not exist in android-9 platform (which we would use instead of android-21).
Wow! I am looking forward to that. |
@DanAlbert: Something which confused me also. And you explained it on android-ndk: The "target" API level for the NDK is not the same as in Java. It's the minimum API level you want to run on. Currently, if APP_PLATFORM is not set, it picks automatically the targetSdkVersion of the AndroidManifest.xml. |
I had to move the native code to its own module with a min SDK, target SDK, and compile tools set to API 21 in order to get the native library to load properly. This started happening after upgrading to |
Sorry, missed this before. Which build system is doing this? I agree, that's the wrong default. |
Thanks for answering anyway! This is "ndk-build" of r13 from command line, on linux 64 bits. Though, there is a warning "Android NDK: WARNING: APP_PLATFORM android-23 is larger than android:minSdkVersion 10 in ./AndroidManifest.xml". my manifest is: |
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=58029 Scenario: Build a project with: * `$(Configuration)`=Release * `$(AotAssemblies)`=True * `$(EnableLLVM)`=True * `$(TargetFrameworkVersion)`=v7.1 (API-25) * `//uses-sdk/@android:minSdkVersion`=10 (in `AndroidManifest.xml`) * with Android NDK r12b or later * on particular hardware devices, e.g. a Nexus 5. Actual results: the app runs, but the AOT'd images aren't used: AOT: image 'Xamarin.Android.Support.v7.AppCompat.dll.so' not found: dlopen failed: cannot locate symbol "__aeabi_memset" referenced by "/data/app/com.companyname.App1-1/lib/arm/libaot-Xamarin.Android.Support.v7.AppCompat.dll.so"... The `__aeabi_memset` symbol can't be found, preventing e.g. `Xamarin.Android.Support.v7.AppCompat.dll.so` from being used. Meaning the app pays the build overhead and size penalty of AOT+LLVM, but doesn't get anything out of it; only the JIT is used. The [cause of the missing `__aeabi_memset` symbol][0] is that we're using the NDK paths which corresponds with `$(TargetFrameworkVersion)`, *not* the NDK paths which correspond with `//uses-sdk/@android:minSdkVersion`. Because of this, if you use the `.apk` on a platform which is >= `minSdkVersion` but less than `$(TargetFrameworkVersion)`, the AOT images won't be used. [0]: android/ndk#126 Fix this by updating the `<Aot/>` task to instead use the `//uses-sdk/@android:minSdkVersion` value. This ensures that we use NDK paths which correspond to the app's minimum supported API level, which should allow the AOT images to be loaded on downlevel devices.
So uh... is there like a way to workaround this issue? I am having this issue and the only comments resembling a solution do not actually work. Bumping compileSdkVersion/targetSdkVersion beyond 23 results in devices (and emulators) with an armv7a chipset running 23 or lower crashing with errors like: |
May be worth noting that I am using gradle so the whole "TODO: No idea" isn't exactly helpful. |
As noted above, you can't do that: https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md |
Found the solution. You can set the NDK target version with android.ndk { |
Is platformVersion the thing it uses? I'm not a gradle user so I don't know how to configure it, but whatever gradle is using for your NDK API level needs to match your minSdkVersion. |
That seems to be the case. Like I noted, I can repro the issue even w/ an emulator. I just added it and the issue seems to be resolved now. |
@DanAlbert Sorry to bring up an old issue, however I am experiencing exactly what you described here (relating to this). I have an OpenGL ES 3.0 project which supports devices on KitKat (API 19) and have the following configuration:
with I now want to use some 3.1 and 3.2 functions on devices that support them so have modified
I have no problem with finding whether these newer functions exist at runtime using |
|
I see, that makes perfect sense. Thank you for the quick reply, I'll go ahead with that route then :) |
Switching targetSDK to 23 from 27 seems to fix the error. Error: dlopen failed: cannot locate symbol "__aeabi_memcpy" referenced by "/data/data/com.mapeo.debug/files/nodejs-project/node_modules/leveldown/build/Release/leveldown.node" See android/ndk#126 and https://android-review.googlesource.com/c/platform/bionic/+/195350
Sorry to bring this up again, but how do I resolve the issue if I have to target 28 and support devices starting from 21? I am using NDK r19c.
|
Stop doing that. Your NDK API level is your |
If I set the NDK API level to 21, it failed with 718
which was fixed in r17b. Now this is a dead end to me. |
it's a mistake to think that globfree() was "fixed" in r17b. glob() and globfree() were added in API 28. you cannot use them in an app that needs to run on earlier OS versions. (a workaround is to copy the source from bionic in AOSP into your app's source.) |
I know this is an old and closed issue for an older version of the NDK, and I apologize for posting here, but I'm going through the exact same issue ( I'm compiling using a standalone toolchain, and my environment setup currently looks like this: export ARCHITECTURE=armv7a-linux-androideabi
export API_LEVEL=16
export NDK_VERSION=20.1.5948944
export NDK=$HOME/Android/Sdk/ndk/$NDK_VERSION/
export HOST_TAG=linux-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
export AR=$TOOLCHAIN/bin/${ARCHITECTURE}-ar
export AS=$TOOLCHAIN/bin/${ARCHITECTURE}-as
export CC=$TOOLCHAIN/bin/${ARCHITECTURE}${API_LEVEL}-clang
export CXX=$TOOLCHAIN/bin/${ARCHITECTURE}${API_LEVEL}-clang++
export LD=$TOOLCHAIN/bin/${ARCHITECTURE}-ld
export RANLIB=$TOOLCHAIN/bin/${ARCHITECTURE}-ranlib
export STRIP=$TOOLCHAIN/bin/${ARCHITECTURE}-strip And my CPPFLAGS looks like this: export CPPFLAGS='-g -fPIC -DANDROID_PLATFORM=android-16 -DAPP_PLATFORM=android-16 -D__ANDROID_API__=16' (I've added the defines for As far as I understand, I'm compiling my binary for anything at API level 16 or above, and yet, it consistently crashes with devices running android 4.x (e.g. 4.3, 4.4.2, all running under armeabi-v7a). Am I overlooking something? Am I doing something stupid? Or is this really an issue? |
Are those flags what you're using to build libtwampc.so? Or is that a prebuilt and it's just a dependency of what you're building? |
Sorry for forgetting such a crucial detail. Those are the flags I'm using to build libtwampc.so and another library used by libtwampc as a dependency. I can load the dependency library just fine, even in the devices where trying to load libtwampc.so fails. |
Could you file a new bug with the |
I have updated from NDK r11c to r12 and there are some missing references when loading my shared library:
(at least):
00000000 DF UND 00000000 LIBC_N __aeabi_memclr4
00000000 DF UND 00000000 LIBC_N __aeabi_memmove
00000000 DF UND 00000000 LIBC_N __aeabi_memclr8
00000000 DF UND 00000000 LIBC_N __aeabi_memcpy
00000000 DF UND 00000000 LIBC_N __aeabi_memcpy4
00000000 DF UND 00000000 LIBC_N __aeabi_memclr
00000000 DF UND 00000000 LIBC_N __aeabi_memset
00000000 DF UND 00000000 LIBC_N __aeabi_atexit
The text was updated successfully, but these errors were encountered: