termux-packages icon indicating copy to clipboard operation
termux-packages copied to clipboard

CMake C compiler ABI detection fails with GCC

Open Leif-W opened this issue 3 years ago • 7 comments

Problem description

Trying to get cmake to use gcc rather than clang fails with Platform/Android/abi--GNU can't be found, due to empty ${CMAKE_ANDROID_ARCH_ABI}.

Steps to reproduce

  • Install cmake from termux repo.
  • Install gcc from its-pointless repo.
  • cmake always seems to prefer clang by default.
  • Change usr/bin/gcc to link to gcc-10 rather than clang-12.
  • Run the setup-parchforgcc script from its-pontless.
  • Simple hello-world project dir, with src/hello-world.c and src/CMakeLists.txt files.
  • Call cmake with either CC=gcc ... or ... -DCMAKE_C_COMPILER=/full/path/to/gcc, same fail result.
  • Error in Android-GNU.cmake saying Platform/Android/abi--GNU can't be found.
  • ${CMAKE_ANDROID_ARCH_ABI} empty when trying to specify gcc.
  • Using clang with either method builds the build system.

Not sure of root cause at this point. Seeking clarification.

Expected behavior

Expect to be able to freely switch between gcc, clang, or any other compiler.

Additional information

Create project:

mkdir -p hello-world/{src,bin}
cd hello-world
echo -e '#include <stdio.h>

int main(void) {
\tprintf("Hello, World!\\n");
\treturn 0;
}' > src/hello-world.c
echo 'cmake_minimum_required(VERSION 3.20)
project(hello-world LANGUAGES C)
add_executable(hello-world hello-world.c)' > src/CMakeLists.txt

Build:

rm -rf bin/*
cmake -DCMAKE_C_COMPILER=`which gcc` -S src -B bin -DCMAKE_BUILD_TYPE=Release

Output:

-- The C compiler identification is GNU 10.2.0
CMake Error at /data/data/com.termux/files/usr/share/cmake-3.20/Modules/Platform/Android-GNU.cmake:29 (include):
  include could not find requested file:

    Platform/Android/abi--GNU
Call Stack (most recent call first):
  /data/data/com.termux/files/usr/share/cmake-3.20/Modules/Platform/Android-GNU-C.cmake:1 (include)
  /data/data/com.termux/files/usr/share/cmake-3.20/Modules/CMakeCInformation.cmake:48 (include)
  CMakeLists.txt:2 (project)


-- Detecting C compiler ABI info
CMake Error at /data/data/com.termux/files/usr/share/cmake-3.20/Modules/Platform/Android-GNU.cmake:29 (include):
  include could not find requested file:

    Platform/Android/abi--GNU
Call Stack (most recent call first):
  /data/data/com.termux/files/usr/share/cmake-3.20/Modules/Platform/Android-GNU-C.cmake:1 (include)
  /data/data/com.termux/files/usr/share/cmake-3.20/Modules/CMakeCInformation.cmake:48 (include)
  /data/data/com.termux/files/home/hello-world/bin/CMakeFiles/CMakeTmp/CMakeLists.txt:2 (project)


CMake Error at /data/data/com.termux/files/usr/share/cmake-3.20/Modules/CMakeDetermineCompilerABI.cmake:49 (try_compile):
  Failed to configure test project build system.
Call Stack (most recent call first):
  /data/data/com.termux/files/usr/share/cmake-3.20/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)
  CMakeLists.txt:2 (project)


-- Configuring incomplete, errors occurred!
See also "/data/data/com.termux/files/home/hello-world/bin/CMakeFiles/CMakeOutput.log".

Leif-W avatar Jun 05 '21 15:06 Leif-W

Until we have a proper fix you can edit $PREFIX/share/cmake-3.20/Modules/Platform/Android-GNU.cmake and replace

include(Platform/Android/abi-${CMAKE_ANDROID_ARCH_ABI}-GNU)

with

include(Platform/Android/abi-arm64-v8a-GNU)

(change arm64-v8a to armeabi-v7a, x86 or x86_64 if you are on arm, i686 or x86_64, respectively)

Grimler91 avatar Jun 05 '21 16:06 Grimler91

Not sure if I understand the cmake modules. Reading the errors, I started with the first error, first file mentioned, Android-GNU.cmake. Yes, CMAKE_ANDROID_ARCH_ABI isn't set there. Looking at all files that set CMAKE_ANDROID_ARCH_ABI, only Android-Determine.cmake sets it. I started at the top, moved down one statement at a time, throwing "HERE" messages message("HERE: ${CMAKE_ANDROID_ARCH_ABI}"), and this value is not set at the beginning, as expected, but then doesn't call HERE messages rather soon, because it return()s. The only clue is a comment.

# Natively compiling on an Android host doesn't use the NDK cross-compilation
# tools.
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android")
  return()
endif()

The thing is, I don't understand yet why Android-Clang.cmake works, as it is very similar. Maybe I was looking into the wrong file? But Android-GNU.cmake is the only file looking for files of the pattern regexp: abi-.*-GNU.cmake. So it has to be here somewhere.

This calls (include()s) Android-Common.cmake, which references CMAKE_ANDROID_ARCH_ABI just once, though seemingly unrelated. But it occurs after a macro() call, possibly setting it? Seems unrelated.

Also looked in CMakeTestCCompiler.cmake and CMakeDetermineCompilerABI.cmake, but not sure if I see anything.

Hard coded value might work-around, but it bugs me not understanding how Clang works, seemingly bypassing the search for arch abi. Maybe the GNU script is called in error or something? Seems like it shouldn't be called unless cross-compiling... Hmm, but Android-Clang.cmake is included twice.

There's a lot of extra NDK related code in the Clang module vs the GNU module. Not sure yet what it all does.

Edit:

Basically, I just copy/pasted Android-Clang.cmake to Android-GNU.cmake, replaced text Clang with GNU, clang with gnu, and commented out an if() block referencing LLVM TRIPLE, whatever that is. CMake appears to build the build system properly. Not sure if right or clean, but seems to work, nothing hard coded.

Leif-W avatar Jun 05 '21 23:06 Leif-W

The solution is very simple, Android-Clang.cmake currently does nothing in Termux. I didn't bother adding that for Android-GNU as neither Termux or the NDK use gcc, feel free to add it yourself and submit a patch.

finagolfin avatar Jun 06 '21 16:06 finagolfin

@buttaface

The solution is very simple, Android-Clang.cmake currently does nothing in Termux.

Exit early, and so no include any Platform/Android/abi--.cmake files, is that the idea? Will submit a patch soon.

Leif-W avatar Jun 06 '21 21:06 Leif-W

This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 18 '21 14:11 stale[bot]

In Android-Clang.cmake line 46-49

if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android")
  macro(__android_compiler_clang lang)
  endmacro()
  return()
endif()

so in Android-GNU.cmake line 27-31 I write

if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android")
  macro(__android_compiler_gnu lang)
  endmacro()
  return()
endif()

yxj-github-437 avatar Sep 08 '22 16:09 yxj-github-437

Yep, that's all that's needed, feel free to submit a pull.

finagolfin avatar Sep 08 '22 18:09 finagolfin