termux-packages
termux-packages copied to clipboard
CMake C compiler ABI detection fails with GCC
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 togcc-10
rather thanclang-12
. - Run the
setup-parchforgcc
script from its-pontless. - Simple
hello-world
project dir, withsrc/hello-world.c
andsrc/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
sayingPlatform/Android/abi--GNU
can't be found. -
${CMAKE_ANDROID_ARCH_ABI}
empty when trying to specifygcc
. - 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".
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)
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.
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.
@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.
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.
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()
Yep, that's all that's needed, feel free to submit a pull.