Skip to content
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

Android NDK build with the ONLY_CBLAS=0 argument #4952

Closed
wholesomemoon opened this issue Oct 24, 2024 · 4 comments
Closed

Android NDK build with the ONLY_CBLAS=0 argument #4952

wholesomemoon opened this issue Oct 24, 2024 · 4 comments

Comments

@wholesomemoon
Copy link

wholesomemoon commented Oct 24, 2024

Hello, I have read through all of #2005 and confirmed that it can be successfully built using the NDK r25 cmake toolchain along with the ONLY_CBLAS=1 parameter. Currently, I am trying to build OpenBLAS-r0.3.28 as a dynamic library for the Android environment, and my host environment is Apple Silicon macOS right now.

# macOS

CMAKE_ARGS+=("-DCMAKE_BUILD_TYPE=Release")
CMAKE_ARGS+=("-DCMAKE_INSTALL_PREFIX=$BUILD_DIR/install")
CMAKE_ARGS+=("-DCMAKE_FIND_FRAMEWORK=NEVER")

CMAKE_ARGS+=("-DBUILD_STATIC_LIBS=OFF")
CMAKE_ARGS+=("-DBUILD_SHARED_LIBS=ON")
CMAKE_ARGS+=("-DBUILD_TESTING=OFF")
CMAKE_ARGS+=("-DONLY_CBLAS=0")

cmake -S . -B $BUILD_DIR "${CMAKE_ARGS[@]}"
cmake --build $BUILD_DIR --target install -- "-j${MAX_JOBS}"
# Android

for ABI in "${ABIS[@]}"
do
  ...
  CMAKE_ARGS+=("-DCMAKE_BUILD_TYPE=Release")
  CMAKE_ARGS+=("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF")
  CMAKE_ARGS+=("-DCMAKE_INSTALL_PREFIX=$BUILD_DIR/install")
  CMAKE_ARGS+=("-DCMAKE_TOOLCHAIN_FILE=$NDK_PATH")
  CMAKE_ARGS+=("-DANDROID_PLATFORM=$TARGET_ANDROID_PLATFORM")
  CMAKE_ARGS+=("-DANDROID_ABI=$ABI")
  
  CMAKE_ARGS+=("-DBUILD_STATIC_LIBS=OFF")
  CMAKE_ARGS+=("-DBUILD_SHARED_LIBS=ON")
  CMAKE_ARGS+=("-DBUILD_TESTING=OFF")
  CMAKE_ARGS+=("-DONLY_CBLAS=0")
  
  if [ $ABI == "arm64-v8a" ]; then
      CMAKE_ARGS+=("-DTARGET=CORTEXA57")
      CMAKE_ARGS+=("-DBINARY=64")
  elif [ $ABI == "armeabi-v7a" ]; then 
      CMAKE_ARGS+=("-DTARGET=ARMV7")
  elif [ $ABI == "x86" ]; then 
      CMAKE_ARGS+=("-DTARGET=ATOM")
  elif [ $ABI == "x86_64" ]; then 
      CMAKE_ARGS+=("-DTARGET=ATOM")
      CMAKE_ARGS+=("-DBINARY=64")
  fi

  cmake -S . -B $BUILD_DIR "${CMAKE_ARGS[@]}"
  cmake --build $BUILD_DIR --target install -- "-j${MAX_JOBS}"
done

However, when I set ONLY_CBLAS=0 for the Android build, I end up with undefined symbol errors for functions like cabsf at the end of the build.

ld: error: undefined symbol: cabsf
>>> referenced by cgbbrd.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/cgbbrd.c.o:(cgbbrd_)
>>> referenced by cgbbrd.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/cgbbrd.c.o:(cgbbrd_)
>>> referenced by cgbsvx.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/cgbsvx.c.o:(cgbsvx_)
>>> referenced 335 more times
>>> did you mean: fabsf
>>> defined in: /Users/user/Library/Android/sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/21/libm.so

ld: error: undefined symbol: csqrtf
>>> referenced by chgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/chgeqz.c.o:(chgeqz_)
>>> referenced by chgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/chgeqz.c.o:(chgeqz_)
>>> referenced by chgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/chgeqz.c.o:(chgeqz_)
>>> referenced 16 more times

ld: error: undefined symbol: cexpf
>>> referenced by clarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/clarnv.c.o:(clarnv_)
>>> referenced by clarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/clarnv.c.o:(clarnv_)
>>> referenced by clarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/clarnv.c.o:(clarnv_)
>>> referenced 3 more times

ld: error: undefined symbol: cabs
>>> referenced by zgbbrd.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zgbbrd.c.o:(zgbbrd_)
>>> referenced by zgbbrd.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zgbbrd.c.o:(zgbbrd_)
>>> referenced by zgbsvx.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zgbsvx.c.o:(zgbsvx_)
>>> referenced 345 more times

ld: error: undefined symbol: csqrt
>>> referenced by zhgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zhgeqz.c.o:(zhgeqz_)
>>> referenced by zhgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zhgeqz.c.o:(zhgeqz_)
>>> referenced by zhgeqz.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zhgeqz.c.o:(zhgeqz_)
>>> referenced 16 more times

ld: error: undefined symbol: cexp
>>> referenced by zlarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zlarnv.c.o:(zlarnv_)
>>> referenced by zlarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zlarnv.c.o:(zlarnv_)
>>> referenced by zlarnv.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/SRC/zlarnv.c.o:(zlarnv_)
>>> referenced 2 more times

ld: error: undefined symbol: csinf
>>> referenced by clatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/clatm5.c.o:(clatm5_)
>>> referenced by clatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/clatm5.c.o:(clatm5_)
>>> referenced by clatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/clatm5.c.o:(clatm5_)
>>> referenced 14 more times

ld: error: undefined symbol: csin
>>> referenced by zlatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/zlatm5.c.o:(zlatm5_)
>>> referenced by zlatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/zlatm5.c.o:(zlatm5_)
>>> referenced by zlatm5.c
>>>               CMakeFiles/LAPACK_OVERRIDES.dir/lapack-netlib/TESTING/MATGEN/zlatm5.c.o:(zlatm5_)
>>> referenced 14 more times
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

If I build with ONLY_CBLAS=0 on macOS Apple Clang instead of using the Android toolchain, the build completes smoothly though. (And as I mentioned earlier, passing the ONLY_CBLAS=1 parameter in Android allows it to build successfully.)
I would appreciate it if somebody could explain why this is not working well.

@martin-frbg
Copy link
Collaborator

Does it build when you leave out the entire -DONLY_CBLAS=0 argument ? But I do not see any connection between this option and the linking of basic math library functions to LAPACK

@wholesomemoon
Copy link
Author

No, the build also fails if I leave out the entire -DONLY_CBLAS=0 argument. I also wonder why the linking libm problem comes out at the end of the build step.

@martin-frbg
Copy link
Collaborator

Ok, there seems to be something "historically" weird with the CMake build - contrary to the Makefile settings, it uses NO_CBLAS only internally and you are supposed to use -DBUILD_WITHOUT_CBLAS instead. Can you please check if this works for you ?
(For reference, I was testing with

cmake -DCMAKE_ANDROID_NDK=/opt/android-ndk-r27 -DTARGET=ARMV8 -DNOFORTRAN=1 -DRANLIB=touch -DBUILD_WITHOUT_CBLAS=0 -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=25 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a  ..

(and for NDK r27 one also needs to increase the ancient cmake_minimum_required in CMakeLists.txt to at least 3.3.0 to avoid some confusing errors - android/ndk#2032
as this has already been requested in #4848, I'll finally fix this later today )

@wholesomemoon
Copy link
Author

wholesomemoon commented Oct 28, 2024

Ok, to let you know, the build was successfully completed by changing the argument you mentioned with the another Android target version. I targeted android-27 using NDK r25 and performed the build on a macOS host environment.

I also confirmed that it works without any linking errors as a third party. Thank you once again, and I'll share the build script here to prevent others from experiencing the same difficulties:

#!/bin/bash
set -e

NDK_TARGET_VERSION=25.1.8937393
TARGET_ANDROID_PLATFORM=android-27
ABIS=("arm64-v8a" "armeabi-v7a" "x86" "x86_64")

if [ "$(uname)" == 'Darwin' ]; then
    NDK_DIR="$HOME/Library/Android/sdk/ndk"
else
    NDK_DIR="$HOME/Android/Sdk/ndk"
fi

if [ ! -d "$NDK_DIR" ]; then
    echo "-- Cannot find NDK directory: $NDK_DIR"
    exit 1
fi

NDK_PATH="$NDK_DIR/$NDK_TARGET_VERSION/build/cmake/android.toolchain.cmake"

if [ ! -f "$NDK_PATH" ]; then
    echo "-- Cannot find NDK toolchain: $NDK_PATH, Please download NDK $NDK_TARGET_VERSION first"
    exit 1
fi

echo "-- Android toolchain file has found: $NDK_PATH"

if [ -z "$MAX_JOBS" ]; then
    if [ "$(uname)" == 'Darwin' ]; then
        MAX_JOBS=$(sysctl -n hw.ncpu)
    else
        MAX_JOBS=$(nproc)
    fi
fi

for ABI in "${ABIS[@]}"
do
    # Build directory for the current ABI
    BUILD_DIR="build/android_$ABI"

    # Remove existing build directory if it exists
    if [ -d "$BUILD_DIR" ]; then
        rm -rf $BUILD_DIR
    fi

    # Create build directory
    mkdir -p $BUILD_DIR

    CMAKE_ARGS=()

    if [ -x "$(command -v ninja)" ]; then
        CMAKE_ARGS+=("-GNinja")
    fi

    CMAKE_ARGS+=("-DCMAKE_BUILD_TYPE=Release")
    CMAKE_ARGS+=("-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF")
    CMAKE_ARGS+=("-DCMAKE_INSTALL_PREFIX=$BUILD_DIR/install")
    CMAKE_ARGS+=("-DCMAKE_TOOLCHAIN_FILE=$NDK_PATH")
    CMAKE_ARGS+=("-DANDROID_PLATFORM=$TARGET_ANDROID_PLATFORM")
    CMAKE_ARGS+=("-DANDROID_ABI=$ABI")

    CMAKE_ARGS+=("-DBUILD_STATIC_LIBS=ON")
    CMAKE_ARGS+=("-DBUILD_SHARED_LIBS=OFF")
    CMAKE_ARGS+=("-DBUILD_TESTING=OFF")
    # CMAKE_ARGS+=("-DONLY_CBLAS=0")
    CMAKE_ARGS+=("-DBUILD_WITHOUT_CBLAS=0")

    if [ $ABI == "arm64-v8a" ]; then
        CMAKE_ARGS+=("-DTARGET=CORTEXA57")
        CMAKE_ARGS+=("-DBINARY=64")
    elif [ $ABI == "armeabi-v7a" ]; then 
        CMAKE_ARGS+=("-DTARGET=ARMV7")
    elif [ $ABI == "x86" ]; then 
        CMAKE_ARGS+=("-DTARGET=ATOM")
    elif [ $ABI == "x86_64" ]; then 
        CMAKE_ARGS+=("-DTARGET=ATOM")
        CMAKE_ARGS+=("-DBINARY=64")
    fi

    # Run CMake configuration
    cmake -S . -B $BUILD_DIR "${CMAKE_ARGS[@]}"

    # Build and install
    cmake --build $BUILD_DIR --target install -- "-j${MAX_JOBS}"
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants