conan icon indicating copy to clipboard operation
conan copied to clipboard

Cannot cross-compile for Android NDK 19C

Open mklaust opened this issue 1 year ago • 2 comments

Describe the bug

After upgrading to Conan 2.6.0, the recipe for libjpeg fails to build when cross-compiling for Android using NDK 19C. (This may be an issue for other recipes/packages as well.)

This issue has been observed when using Ubuntu 22.04 and Windows 11 build systems.

Here are the key/related items from the host profile:

[settings]
os=Android
os.api_level=16
arch=armv7
compiler=clang
compiler.version=8
compiler.cppstd=gnu17
compiler.libcxx=c++_shared
build_type=Release

[conf]
tools.android:ndk_path=<This is set to the unzipped path of Android NDK 19c>

(I can't share our entire setup, but if you need additional information, please let me know.)

The following Conan command triggers this problem:

conan install --requires libjpeg/9e -pr:b gcc11-linux-x64 -pr:h clang8-android-armv7 -s:b build_type=Debug -s:h build_type=Debug --build="libjpeg/9e"

Here's the offending error from the output...

./libtool: line 1720: /opt/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib: No such file or directory

This may have been caused by a recent change to Conan file gnutoolchain.py. Starting at line 159 it sets several variables used for the cross-compile. For some, it uses the file based on the target and API level. However, for the RANLIB variable, it uses the hard-coded filename of llvm-ranlib. In the most recent version of the NDK (and possibly others) this file exists. However, in the 19C version, this file does NOT exist, which causes the build to fail. Due to factors outside of our control, we need to use version 19C, so we're trying to figure out a solution that will work for that version.

I've tried various approaches to set RANLIB in the host profile we're using but nothing seems to overwrite the value set by this script. The only ways I've been able to get this to work thus far is to:

  • Manually modify the generated libtool and Makefile files generated to specify the correct ranlib filename.
  • Create a symbolic link for the file it is looking for (llvm-ranlib) that points to the actual file arm-linux-androideabi-ranlib.

I would consider both of these a hack, not a fix.

It seems that line 164 should be using a value that correlates with the information provided in host profile rather than just hard-coding it to llvm-ranlib.

I'm struggling to figure out a non-ugly workaround for this. We build for various target platforms including 4 different Android configurations. I can't just use the symbolic link approach as it would only work for ARM-based builds.

Is there any way to configure the profile (or some other file) that would force Conan to use a custom value for RANLIB? I know that some of the settings for doing cross-compiles for Android have changed over the versions. I'm hoping that there is some new way to do this that I just haven't found yet.

How to reproduce it

The following Conan command triggers this problem:

conan install --requires libjpeg/9e -pr:b gcc11-linux-x64 -pr:h clang8-android-armv7 -s:b build_type=Debug -s:h build_type=Debug --build="libjpeg/9e"

mklaust avatar Aug 09 '24 18:08 mklaust

Thanks for reporting this @mklaust

Tagging @franramirez688 - as we may need some improvements:

  • document and check the minimum required version of the android ndk for those variables to be set - I think the ones we are setting are valid since ndk 22
  • check if the files exist before setting the variables

@mklaust we'll look into this and if necessary issue a patch release for 2.6.0 - as I can see that the variables set by the autotoolstoolchain do take precedence over any variable set (or unset) by the user.

Due to factors outside of our control, we need to use version 19C, so we're trying to figure out a solution that will work for that version.

Our understanding of the Android NDK is that newer versions of the NDK can be used to target older versions of Android - so one could still generate the same binaries with newer versions of the NDK. Is this not correct? Any information would be appreciated as it can inform of our policy of how far we should go in supporting older versions, since 19C is arguably quite old.

jcar87 avatar Aug 10 '24 09:08 jcar87

@jcar87 you are correct in that newer versions of the NDK can be used to target older versions of Android. Our challenge is that we're linking in other binaries (not ours) that are also built with 19C, which is what's holding us to that version. There are efforts/plans to upgrade. (As you said...19C is quite old.) Unfortunately, until that happens, we're stuck at this version.

I appreciate the feedback and the possibility of a patch! If you discover a way for us to override this behavior (using the existing logic), I'm good with that too. The workarounds I listed in the original post are the only ones I've found thus far, but there are some challenges associated with them.

Thanks again!

mklaust avatar Aug 12 '24 11:08 mklaust

This has been closed by https://github.com/conan-io/conan/pull/17470, that will prioritize Conan defined buildenv (from profiles or from tool-requires). So if the environment define CC/CXX/... variables, then the AutotoolsToolchain will not automatically deduce and define it from the ndk_path. This will be part of Conan 2.11 to be released asap.

memsharded avatar Dec 18 '24 11:12 memsharded