Skip to content

Conversation

olliwang
Copy link

Since Android NDK r23+, unwind support is bundled in the Clang toolchain and explicit linking to libunwind is no longer required. Linking this library causes build errors on modern NDKs.

This change removes libunwind from the configure options to ensure successful builds for NDK r23+.

  • I've followed this guide step by step carefully. Yes

Clang-based Android NDKs bundle unwind support and do not require explicit linking. Passing malformed flags like "-l-l:libunwind.a" caused build failures with ld.lld on NDK r23+. This change removes those flags from configure options to ensure successful builds.
@NeroBurner NeroBurner added the enhancement New feature or request label Sep 16, 2025
@NeroBurner
Copy link

sounds reasonable. I have no experience in Android toolchains thoug.

Android build seems to still fail (probably a different error)

Please ping me when you are happy with the state of this PR

@olliwang
Copy link
Author

sounds reasonable. I have no experience in Android toolchains thoug.

Android build seems to still fail (probably a different error)

Please ping me when you are happy with the state of this PR

@NeroBurner Yes, I've tested on NDK 23+ and it works perfectly. Thanks :)

@NeroBurner
Copy link

Could you explain to me why the CI / OpenSSL android-ndk-api-35-arm64-v8a-libcxx14 ubuntu-24.04 toolchain fails? Is the NDK 23+ thing different to the API? Just so I have a ROUGH understanding what is happening here and having a slight chance that the toolchain may be fixed

@olliwang
Copy link
Author

olliwang commented Sep 16, 2025

Could you explain to me why the CI / OpenSSL android-ndk-api-35-arm64-v8a-libcxx14 ubuntu-24.04 toolchain fails? Is the NDK 23+ thing different to the API? Just so I have a ROUGH understanding what is happening here and having a slight chance that the toolchain may be fixed

I cannot find the source code of android-ndk-api-35-arm64-v8a-libcxx14.cmake but I am guessing the toolchain is very old. I remembered the original Android toolchain only support NDK 16 or 17. I modified mine long time ago to support NDK 22. Now I have to update to NDK 28 because Google Play requires support for 16 KB page sizes now and NDK 28 will build C++ libraries for 16 KB page size out-of-box.

@NeroBurner
Copy link

On current master (roughly Hunter v0.26.3) the mentioned error with libunwind is present (which this PR fixes 🎉 ):

/usr/local/lib/android/sdk/ndk/27.3.13750724/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -fPIC -pthread -Wall -O3 -L. -Wl,-z,defs -Wl,-znodelete -shared -Wl,-Bsymbolic   \
	-o providers/legacy.so -Wl,--version-script=providers/legacy.ld \
	providers/legacy-dso-legacyprov.o \
	providers/liblegacy.a providers/libcommon.a -lcrypto -ldl -pthread -latomic -Wl,--build-id=sha1 -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--gc-sections -Qunused-arguments -Wl,--no-undefined  -Wl,--gc-sections -latomic -lm -lc++ -lm -l-l:libunwind.a -ldl -lc -l-l:libunwind.a -ldl
ld.lld: error: unable to find library -l-l:libunwind.a
ld.lld: error: unable to find library -l-l:libunwind.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I see that the Toolchain runs on the provided ndk 27.3

The build matrix of master shows that the android build, the windows store build and the ios-nocodesign builds were already failing

master build matrix

In this PR essentially the same 3 toolchains are failing:

PR toolchains

The error for the android toolchain is different:

/usr/local/lib/android/sdk/ndk/27.3.13750724/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -fPIC -pthread -Wall -O3 -L. -Wl,-z,defs -Wl,-znodelete -shared -Wl,-Bsymbolic   \
	-o providers/legacy.so -Wl,--version-script=providers/legacy.ld \
	providers/legacy-dso-legacyprov.o \
	providers/liblegacy.a providers/libcommon.a -lcrypto -ldl -pthread -latomic -Wl,--build-id=sha1 -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--gc-sections -Qunused-arguments -Wl,--no-undefined  -Wl,--gc-sections -latomic -lm -lc++ -lm  -ldl -lc  -ldl
ld.lld: error: providers/legacy-dso-legacyprov.o is incompatible with elf64-x86-64
ld.lld: error: providers/liblegacy.a(liblegacy-lib-cipher_blowfish.o) is incompatible with elf64-x86-64
ld.lld: error: providers/liblegacy.a(liblegacy-lib-cipher_blowfish_hw.o) is incompatible with elf64-x86-64
ld.lld: error: providers/liblegacy.a(liblegacy-lib-cipher_cast5.o) is incompatible with elf64-x86-64

@NeroBurner
Copy link

I cannot find the source code of android-ndk-api-35-arm64-v8a-libcxx14.cmake but I am guessing the toolchain is very old

Or I created it wrong 😅 I changed their creation in #780

The toolchains are generated now by the .github/workflows/set_matrix.py script. If you want to create the toolchains for the OpenSSL project run the following:

python3 .github/workflows/set_matrix.py OpenSSL

Then you'll get the toolchain files in .github/toolchains/android-ndk-api-35-arm64-v8a-libcxx14.cmake

The toolchain file looks as follows:

# toolchain file generated by set_matrix.py, do not modify!
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_SYSTEM_VERSION "35") # API level
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK}") # provided by GitHub

string(COMPARE EQUAL "${CMAKE_ANDROID_NDK}" "" _is_empty)
if(_is_empty)
  message(FATAL_ERROR
      "Environment variable 'ANDROID_NDK' not set"
  )
endif()

# ANDROID macro is not defined by CMake 3.7+, however it is used by
# some packages like OpenCV
# (https://gitlab.kitware.com/cmake/cmake/merge_requests/62)
add_definitions("-DANDROID")
set(CMAKE_ANDROID_STL_TYPE "c++_static") # LLVM libc++ static
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} -stdlib=libc++")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Is it grossly wrong? 😅

@NeroBurner NeroBurner merged commit c8a3b2c into cpp-pm:master Sep 16, 2025
13 of 16 checks passed
@NeroBurner NeroBurner changed the title OpenSSL: drop libunwind linking for Clang-based NDK OpenSSL: drop libunwind linking for Clang-based Android NDK Sep 16, 2025
@olliwang
Copy link
Author

I cannot find the source code of android-ndk-api-35-arm64-v8a-libcxx14.cmake but I am guessing the toolchain is very old

Or I created it wrong 😅 I changed their creation in #780

The toolchains are generated now by the .github/workflows/set_matrix.py script. If you want to create the toolchains for the OpenSSL project run the following:

python3 .github/workflows/set_matrix.py OpenSSL

Then you'll get the toolchain files in .github/toolchains/android-ndk-api-35-arm64-v8a-libcxx14.cmake

The toolchain file looks as follows:

# toolchain file generated by set_matrix.py, do not modify!
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_SYSTEM_VERSION "35") # API level
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK}") # provided by GitHub

string(COMPARE EQUAL "${CMAKE_ANDROID_NDK}" "" _is_empty)
if(_is_empty)
  message(FATAL_ERROR
      "Environment variable 'ANDROID_NDK' not set"
  )
endif()

# ANDROID macro is not defined by CMake 3.7+, however it is used by
# some packages like OpenCV
# (https://gitlab.kitware.com/cmake/cmake/merge_requests/62)
add_definitions("-DANDROID")
set(CMAKE_ANDROID_STL_TYPE "c++_static") # LLVM libc++ static
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} -stdlib=libc++")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Is it grossly wrong? 😅

This is the toolchain I’m using now. It has worked for several years across all the updates of Android Studio.

# STEP 1: Lock variables from Gradle build

set(ANDROID_ABI "@ANDROID_ABI@")
set(ANDROID_PLATFORM "@ANDROID_PLATFORM@")
set(ANDROID_STL "@ANDROID_STL@")
set(CMAKE_ANDROID_ARCH_ABI "@CMAKE_ANDROID_ARCH_ABI@")
set(CMAKE_ANDROID_STL_TYPE "c++_static")
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@")

# STEP 2: Include original toolchain

# Original toolchain file will be saved in variable:
# * _ORIGINAL_TOOLCHAIN_FILE

if("@_ORIGINAL_TOOLCHAIN_FILE@" STREQUAL "")
  # Variable not set, initial project configuration.
  # Path to original Android NDK toolchain saved in CMAKE_TOOLCHAIN_FILE.
  if("@CMAKE_TOOLCHAIN_FILE@" STREQUAL "")
    message(FATAL_ERROR "Unexpected: CMAKE_TOOLCHAIN_FILE is empty")
  endif()

  if(NOT EXISTS "@CMAKE_TOOLCHAIN_FILE@")
    message(FATAL_ERROR "File not found: '@CMAKE_TOOLCHAIN_FILE@'")
  endif()

  set(_original_toolchain_file "@CMAKE_TOOLCHAIN_FILE@")
else()
  set(_original_toolchain_file "@_ORIGINAL_TOOLCHAIN_FILE@")
endif()

set(
  _ORIGINAL_TOOLCHAIN_FILE
  "${_original_toolchain_file}"
  CACHE
  PATH
  "Original Android NDK toolchain"
)

if(NOT "${_ORIGINAL_TOOLCHAIN_FILE}" STREQUAL "${CMAKE_CURRENT_LIST_FILE}")
  include("${_ORIGINAL_TOOLCHAIN_FILE}")
endif()

# STEP 3: Fix Android NDK

if ("@_CMAKE_ANDROID_NDK@" STREQUAL "" AND
    NOT "@CMAKE_ANDROID_NDK@" STREQUAL "")
  set(
    _CMAKE_ANDROID_NDK
    "@CMAKE_ANDROID_NDK@"
    CACHE
    PATH
    "Original Android NDK"
  )
  set(CMAKE_ANDROID_NDK "@CMAKE_ANDROID_NDK@")
elseif("${CMAKE_ANDROID_NDK}" STREQUAL "")
  set(CMAKE_ANDROID_NDK "@_CMAKE_ANDROID_NDK@")
endif()

# STEP 4: Tweak CMake Android variables

set(CMAKE_SYSTEM_VERSION "${ANDROID_NATIVE_API_LEVEL}")

# STEP 5: Custom user variables

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

@NeroBurner
Copy link

Could you provide a filled out version as well? This could be very helpful. Thanks!

@olliwang
Copy link
Author

Could you provide a filled out version as well? This could be very helpful. Thanks!

Sure. This toolchain was modified based on the original Android toolchain. Be aware that I’m targeting C++20 for my purposes. It works well with all the Hunter packages I’m using, though I definitely haven’t tested every package.

# Copyright (c) 2018, Ruslan Baratov
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# For the latest version of this file and working example see:

# For the example and for the latest version of this file check:
# * https://github.com/forexample/android-studio-with-hunter

# Hunter need stand-alone toolchain that will not depend
# on any ANDROID_* variables:
# * https://docs.hunter.sh/en/latest/overview/customization/toolchain-id.html

# To achieve this we need to make a 3 steps:
# * Lock CMake variables that coming from Gradle build
# * Include original Android toolchain from NDK
# * Add any custom user variables

# STEP 1: Lock variables from Gradle build

set(ANDROID_ABI "@ANDROID_ABI@")
set(ANDROID_PLATFORM "@ANDROID_PLATFORM@")
set(ANDROID_STL "@ANDROID_STL@")
set(CMAKE_ANDROID_ARCH_ABI "@CMAKE_ANDROID_ARCH_ABI@")
set(CMAKE_ANDROID_STL_TYPE "c++_static")
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@")

# STEP 2: Include original toolchain

# Original toolchain file will be saved in variable:
# * _ORIGINAL_TOOLCHAIN_FILE

if("@_ORIGINAL_TOOLCHAIN_FILE@" STREQUAL "")
  # Variable not set, initial project configuration.
  # Path to original Android NDK toolchain saved in CMAKE_TOOLCHAIN_FILE.
  if("@CMAKE_TOOLCHAIN_FILE@" STREQUAL "")
    message(FATAL_ERROR "Unexpected: CMAKE_TOOLCHAIN_FILE is empty")
  endif()

  if(NOT EXISTS "@CMAKE_TOOLCHAIN_FILE@")
    message(FATAL_ERROR "File not found: '@CMAKE_TOOLCHAIN_FILE@'")
  endif()

  set(_original_toolchain_file "@CMAKE_TOOLCHAIN_FILE@")
else()
  set(_original_toolchain_file "@_ORIGINAL_TOOLCHAIN_FILE@")
endif()

set(
  _ORIGINAL_TOOLCHAIN_FILE
  "${_original_toolchain_file}"
  CACHE
  PATH
  "Original Android NDK toolchain"
)

if(NOT "${_ORIGINAL_TOOLCHAIN_FILE}" STREQUAL "${CMAKE_CURRENT_LIST_FILE}")
  include("${_ORIGINAL_TOOLCHAIN_FILE}")
endif()

# STEP 3: Fix Android NDK

if ("@_CMAKE_ANDROID_NDK@" STREQUAL "" AND
    NOT "@CMAKE_ANDROID_NDK@" STREQUAL "")
  set(
    _CMAKE_ANDROID_NDK
    "@CMAKE_ANDROID_NDK@"
    CACHE
    PATH
    "Original Android NDK"
  )
  set(CMAKE_ANDROID_NDK "@CMAKE_ANDROID_NDK@")
elseif("${CMAKE_ANDROID_NDK}" STREQUAL "")
  set(CMAKE_ANDROID_NDK "@_CMAKE_ANDROID_NDK@")
endif()

# STEP 4: Tweak CMake Android variables

set(CMAKE_SYSTEM_VERSION "${ANDROID_NATIVE_API_LEVEL}")

# STEP 5: Custom user variables

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

@NeroBurner
Copy link

With filled out I was referring to have the template variables like "@ANDROID_ABI@" filled out with the actual values. Sorry for being unclear

@olliwang
Copy link
Author

With filled out I was referring to have the template variables like "@ANDROID_ABI@" filled out with the actual values. Sorry for being unclear

It's arm64-v8a in my environment.

@NeroBurner
Copy link

And all the other values? Can you copy the final version after all the @@ template variables got filled out with your environment variables? 🙏

@olliwang
Copy link
Author

And all the other values? Can you copy the final version after all the @@ template variables got filled out with your environment variables? 🙏

No problem. They look like this:

@ANDROID_ABI@: arm64-v8a
@ANDROID_PLATFORM@: android-26
@ANDROID_STL@: c++_static
@CMAKE_ANDROID_ARCH_ABI@: arm64-v8a
@CMAKE_ANDROID_NDK@: /Users/username/Library/Android/sdk/ndk/28.2.13676358
@CMAKE_TOOLCHAIN_FILE@: /Users/username/Developer/proj/src/android/app/.cxx/Debug/6nb1j5q5/arm64-v8a/shared/nanoi/nanoi/generated/toolchain.cmake
@CMAKE_SYSTEM_VERSION@: 26
@_CMAKE_ANDROID_NDK@: /Users/username/Library/Android/sdk/ndk/28.2.13676358
@_ORIGINAL_TOOLCHAIN_FILE@: /Users/username/Library/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake

@olliwang
Copy link
Author

BTW, I also have some fixes for other packages built with the latest iOS 26 / macOS 26 SDK. Could you take a look at them as well?

libpng: hunter-packages/libpng#9
zlib: cpp-pm/zlib#2

I submitted these pull requests because the current versions cause build errors with the newer SDK, which was officially released this month.

@NeroBurner
Copy link

Thank you very much. I'll try to take a look as soon as possible. Thanks again for your contributions!

@NeroBurner
Copy link

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

Successfully merging this pull request may close these issues.

2 participants