opensearch-project / k-NN

🆕 Find the k-nearest neighbors (k-NN) for your vector data
https://opensearch.org/docs/latest/search-plugins/knn/index/
Apache License 2.0
156 stars 123 forks source link

[Enhancement] Update DEVELOPER_GUIDE md file regarding to clang++19 building failure in Mac ARM64 arc. #2272

Open 0ctopus13prime opened 1 week ago

0ctopus13prime commented 1 week ago

Description

When try to build JNI plugin with clang++19, several errors have been occurred. However, in DEVELOPER_GUIDE we don't have much to say about these failures. It would be good to introduce a new section in there regarding how user can solve the building failures in Mac.

Assumption

User will bump into these issues after they installed llvm via brew. (llvm@19) https://formulae.brew.sh/formula/llvm

⚡  clang++ --version
Homebrew clang version 19.1.3
Target: arm64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/19.1.3/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin23.cfg

Failures

Before applying below listed solutions, you have to make sure

  1. No CMakeFiles, CMakeCache.txt and Makefile under jni, external/faiss and external/nmslib.
  2. Ensure cmake is using clang 19.
⚡  cmake . --fresh
Re-run cmake no build system arguments
-- The C compiler identification is Clang 19.1.3
-- The CXX compiler identification is Clang 19.1.3
-- Detecting C compiler ABI info
...

1. std::promise symbol not found

Undefined symbols for architecture arm64:
  "std::exception_ptr::__from_native_exception_pointer(void*)", referenced from:
      std::__1::promise<bool>::~promise() in libfaiss.a[79](WorkerThread.cpp.o)
  "___cxa_init_primary_exception", referenced from:
      std::__1::promise<bool>::~promise() in libfaiss.a[79](WorkerThread.cpp.o)
ld: symbol(s) not found for architecture arm64
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [release/libopensearchknn_faiss.jnilib] Error 1
make[1]: *** [CMakeFiles/opensearchknn_faiss.dir/all] Error 2
make: *** [all] Error 2

Solution: As the error message suggests, it is failing to get the actual symbol of a std::promise<bool> desctructor during linking time. This can be resolved if we can provide a proper linking path to enable builder to locate the right symbol it wants.

  1. You can use g++ to rebuild the entire project.
  2. Or add this line under https://github.com/opensearch-project/k-NN/blob/main/jni/CMakeLists.txt#L117
    1. target_link_options(${TARGET_LIB_FAISS} PRIVATE "-L/opt/homebrew/opt/llvm/lib/c++")
    2. /opt/homebrew/opt/llvm/lib/c++ can be acquired -L"$(brew --prefix llvm)"/lib/c++
  3. You will likely hit the same error when building jni_test, and you can address the issue add the same line with a target jni_test.
    1. target_link_options(jni_test PRIVATE "-L/opt/homebrew/opt/llvm/lib/c++")

Why it's failing? Looks like there's a linking issue in clang - https://github.com/Homebrew/homebrew-core/issues/169820

2. Standard library include header not found

[  0%] Building CXX object CMakeFiles/opensearchknn_util.dir/src/jni_util.cpp.o
clang++: warning: -lomp: 'linker' input unused [-Wunused-command-line-argument]
clang++: warning: argument unused during compilation: '-L/opt/homebrew/opt/libomp/lib' [-Wunused-command-line-argument]
In file included from /Users/neetiks/workspace/k-NN/jni/src/jni_util.cpp:12:
/Users/neetiks/workspace/k-NN/jni/include/jni_util.h:16:10: fatal error: 'stdexcept' file not found
   16 | #include <stdexcept>
      |          ^~~~~~~~~~~
1 error generated.

Solution:

  1. Remove CMakeFiles, CMakeCache.txt and Makefile under jni, external/faiss and external/nmslib.
  2. export CC=clang
  3. export CXX=clang++
  4. Ensure cmake is using clang 19.

3. Fortran symbols not found

Undefined symbols for architecture arm64:
  "__gfortran_concat_string", referenced from:
      _sgesvd_ in libopenblas.a[6288](sgesvd.o)
      _sgesvd_ in libopenblas.a[6288](sgesvd.o)
      _sormbr_ in libopenblas.a[6415](sormbr.o)
      _sormbr_ in libopenblas.a[6415](sormbr.o)
      _sormbr_ in libopenblas.a[6415](sormbr.o)
      _sormbr_ in libopenblas.a[6415](sormbr.o)
      _sormlq_ in libopenblas.a[6418](sormlq.o)
      _sormlq_ in libopenblas.a[6418](sormlq.o)
      _sormlq_ in libopenblas.a[6418](sormlq.o)
      ...
ld: symbol(s) not found for architecture arm64

I'm still working on it why this is happening, but suspecting the downloaded libopenblas.a from brew is not compatible with ARM 64 architecture. Once we remove below line from jni/CMakeCache.txt, it would work.

Remove this vvvvvvvvvvvvvvvvvvvvvvv
BLAS_openblas_LIBRARY:FILEPATH=/opt/homebrew/opt/openblas/lib/libopenblas.a
navneet1v commented 1 week ago

Thanks @0ctopus13prime for starting this issue.