Skip to content

Fix android ndk clang#21222

Closed
holmesconan wants to merge 13 commits intomicrosoft:masterfrom
holmesconan:fix-android-ndk-clang
Closed

Fix android ndk clang#21222
holmesconan wants to merge 13 commits intomicrosoft:masterfrom
holmesconan:fix-android-ndk-clang

Conversation

@holmesconan
Copy link

This is a fix of Android triplets that using clang as the default compiler.

  • What does your PR fix?

    Fix vcpkg_configure_make based port cannot find gcc (aka clang) compiler during config stage
    Fix ANDROID_NATIVE_API_LEVEL only detected from CMAKE_SYSTEM_VERSION, add ENV{ANDROID_API_LEVEL} for customizing

  • Which triplets are supported/not supported? Have you updated the CI baseline?

    android, No

  • Does your PR follow the maintainer guide?

    Yes

  • If you have added/updated a port: Have you run ./vcpkg x-add-version --all and committed the result?

    No

If you are still working on the PR, open it as a Draft: https://github.blog/2019-02-14-introducing-draft-pull-requests/

@ghost
Copy link

ghost commented Nov 6, 2021

CLA assistant check
All CLA requirements met.

@holmesconan
Copy link
Author

The only notification is that, please add Android NDK toolchain executable path:

export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/<host-tag>/bin:$PATH

host-tag is linux-x86_64 on linux and 'darwin-x86_64' on osx. Windows is not tested yet.

Copy link
Contributor

@dg0yt dg0yt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. This is just a quick review in Github.

# Android - cross-compiling support
if(VCPKG_TARGET_IS_ANDROID)
if (VCPKG_DETECTED_CMAKE_CXX_COMPILER_ID MATCHES "^Clang$")
string(REPLACE "-static-libstdc++" "-lc++_static" VCPKG_DETECTED_CMAKE_CXX_STANDARD_LIBRARIES ${VCPKG_DETECTED_CMAKE_CXX_STANDARD_LIBRARIES})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why this should be wrong in the detected libraries. IIRC, the NDK's toolchain has variables to configure the C++ runtime. Can't we hook into chainloading and configuring this toolchain, and then leave the detected values untouched?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot answer this. I have tried to hook the <VCPKG_ROOT>/scripts/toolchains/android.cmake for adding some util variables, but it seems that vcpkg_configure_make.cmake do not reference that file. So I have to specify the ANDROID_API_LEVEL again. So I do not think it is easy to hook NDK's toolchain file to obtain the detected. Or if I could fully understand how to do it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This export should be done in the CMakeLists.txt of vcpkg_get_cmake_vars so that meson and other buildsystems are also informed about the required flags.

set(ANDROID_API_LEVEL $ENV{ANDROID_API_LEVEL} CACHE STRING "")
else()
set(ANDROID_API_LEVEL ${VCPKG_DETECTED_CMAKE_SYSTEM_VERSION} CACHE STRING "")
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if respecting ENV{ANDROID_API_LEVEL} at this point may break binary caching.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes, it would be. Since different API level may have different ABI, especially for the libc++. If one library is compiled with ANDROID_API_LEVEL equals 21, but others with 23, for example. They could not be linked into the final .so file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should consider ENV{ANDROID_API_LEVEL} here?

set(base_cmd)
if(CMAKE_HOST_WIN32)
set(base_cmd ${bash_executable} --noprofile --norc --debug)
set(base_cmd ${BASH} --noprofile --norc --debug)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no BASH here. I think this was renamed to bash_executable as part of the script audit, parallel to your work.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I checked the upstream version, I will fix it. It was caused by merging without check. shame.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caused the CI to fail. fixed.

# -avoid-version is handled specially by libtool link mode, this flag is not forwarded to linker,
# and libtool tries to avoid versioning for shared libraries and no symbolic links are created.
if(VCPKG_TARGET_IS_ANDROID)
if(VCPKG_TARGET_IS_ANDROID AND VCPKG_DETECTED_CMAKE_C_COMPILER_ID MATCHES "^GNU$")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it needed, or does it break, with clang?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: STREQUAL "GNU" would suffice.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, it just generated a warning for argument unused during compilation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is removed. God bless no weird problems happen.

Copy link
Contributor

@dg0yt dg0yt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not unconditionally override (set) arg_BUILD_TRIPLET for Android. It is a valid argument to be supplied by the calling portfile, and it may be overridden by the triplet file. Even if not used in vcpg at the moment, this is public interface possibly used in user's ports or triplets.
The pattern for windows and macos is:

if(VCPKG_TARGET_IS_ANDROID)
    if(arg_DETERMINE_BUILD_TRIPLET OR NOT arg_BUILD_TRIPLET)
        ...
        set(arg_BUILD_TRIPLET ...

# shell which will be otherwise identified as ${BUILD_ARCH}-pc-msys
elseif(VCPKG_HOST_IS_OSX)
z_vcpkg_determine_autotools_host_arch_mac(BUILD_ARCH) # machine you are building on => --build=
set(arg_BUILD_TRIPLET "--build=${BUILD_ARCH}-apple-darwin${VCPKG_CMAKE_HOST_SYSTEM_VERSION}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the last variable is named VCPKG_DETECTED_CMAKE_HOST_SYSTEM_VERSION.

@JackBoosY JackBoosY added category:community-triplet A PR or issue related to community triplets not officially validated by the vcpkg team. category:tool-update The issue is with build tool or build script, which requires update or should be executed correctly labels Nov 8, 2021
@JackBoosY
Copy link
Contributor

Failed to build python3:x64-osx:

configure: WARNING: unrecognized options: --disable-silent-rules, --enable-static
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
./../src/v3.10.0-dcf0f0f52f.clean/configure: line 10530: PKG_PROG_PKG_CONFIG: command not found
./../src/v3.10.0-dcf0f0f52f.clean/configure: line 10673: /usr/local/bin/pkg-config --static: No such file or directory
configure: WARNING: unrecognized options: --disable-silent-rules, --enable-static

@dg0yt
Copy link
Contributor

dg0yt commented Nov 8, 2021

Failed to build python3:x64-osx

I wonder how this PR can have a side effect on /usr/local/bin/pkg-config --static being considered a single value ("No such file or directory") instead of a list for python3:x64-osx.

@dg0yt
Copy link
Contributor

dg0yt commented Nov 8, 2021

Failed to build python3:x64-osx

I wonder how this PR can have a side effect on /usr/local/bin/pkg-config --static being considered a single value ("No such file or directory") instead of a list for python3:x64-osx.

Well, there is one changed line which is unrelated to android, but very much related to x64-osx:

if(host_arch MATCHES "(amd|AMD|x86_|X86_)64")

This change is reasonable, but maybe it needs investigation in a separate PR. By changing host detection, the cross-build property will change to, and this can uncover bugs in other ports.

@holmesconan
Copy link
Author

made a little changes for the z_vcpkg_determine_autotools_host_cpu. if it doesn't resolve the problem, I cannot fix it now. My Macbook is dead.....

@holmesconan
Copy link
Author

More tests on Android libraries are needed. Anyone who have problems are welcome.

@JackBoosY
Copy link
Contributor

Please ping me if this PR is ready for review.

Also, cc @Neumann-A for review the configure_make part.

@holmesconan
Copy link
Author

@JackBoosY Yes, it is ready for review. @Neumann-A

@JackBoosY JackBoosY marked this pull request as ready for review November 10, 2021 07:24
@JackBoosY JackBoosY added the requires:vcpkg-team-review This PR or issue requires someone on the vcpkg team to take a further look. label Nov 11, 2021
set(ANDROID_API_LEVEL $ENV{ANDROID_API_LEVEL} CACHE STRING "")
else()
set(ANDROID_API_LEVEL ${VCPKG_DETECTED_CMAKE_SYSTEM_VERSION} CACHE STRING "")
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why we should consider ENV{ANDROID_API_LEVEL} here?

Comment on lines +504 to +515
if (TARGET_ARCH MATCHES "armv7-a")
string(APPEND configure_env " CC=armv7a-linux-androideabi${ANDROID_API_LEVEL}-clang")
string(APPEND configure_env " CXX=armv7a-linux-androideabi${ANDROID_API_LEVEL}-clang++")
else()
string(APPEND configure_env " CC=${TARGET_ARCH}-linux-android${ANDROID_API_LEVEL}-clang")
string(APPEND configure_env " CXX=${TARGET_ARCH}-linux-android${ANDROID_API_LEVEL}-clang++")
endif()

string(APPEND configure_env " AR=llvm-ar")
string(APPEND configure_env " RANLIB=llvm-ranlib")
string(APPEND configure_env " READELF=llvm-readelf")
string(APPEND configure_env " STRIP=llvm-strip")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply no. Setup the toolchain correctly..... CC and CXX and the rest of the programs should be correctly setup by cmake.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the ENV{ANDROID_API_LEVEL} since I don't want to add another argument for vcpkg_configure_make. It needs more consideration about the general purpose. It seems that an argument is reasonable? One need to customize the ANDROID API LEVEL instead of the detected version.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the CC and CXX environment variables are the core patch of this PR. Without that, the autotools configure script could not find the compiler properly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the CC and CXX environment variables are the core patch of this PR

but not in this way because it is too specific. If necessary there needs to be a simple branch which setups all progs correctly to the VCPKG_DETECTED_ variables (like in the windows branch)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toolchain did not correctly setup by cmake since it was out of control. When reading config-x86-android-dbg-out.txt in buildtree//, I found that most cross-compile toolchains are grabbed from the system, not in the NDK. It won't work. So I need to manually specify the toolchain through configure_env.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say that is not a problem for vcpkg_configure_make to solve.

CMAKE_HOST_SYSTEM_PROCESSOR)
CMAKE_HOST_SYSTEM_PROCESSOR
CMAKE_SYSTEM_VERSION
CMAKE_HOST_SYSTEM_VERSION)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CMAKE_HOST_SYSTEM_VERSION)

don't see why we should care about CMAKE_HOST_SYSTEM_VERSION. vcpkg should only focus on building for the target.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When cross-compile python3, one needs to specify the --build option and on osx, it will be x86_64-apple-darwin20.6.0, where 20.6.0 is the host system version in cmake. In other words, when cross-compile some libraries on osx, one may need that variable. Yes I will shrink it to CMAKE_HOST_SYSTEM_VERSION only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When cross-compile python3

that seems oddly specific to python3. The typically configure scripts don't care about anything after *-darwin*

Comment on lines +6 to +13
if (DEFINED ENV{ANDROID_API_LEVEL})
set(ANDROID_NATIVE_API_LEVEL $ENV{ANDROID_API_LEVEL} CACHE STRING "")
set(ANDROID_PLATFORM $ENV{ANDROID_API_LEVEL} CACHE STRING "")
else()
set(ANDROID_NATIVE_API_LEVEL ${CMAKE_SYSTEM_VERSION} CACHE STRING "")
set(ANDROID_PLATFORM ${CMAKE_SYSTEM_VERSION} CACHE STRING "")
endif()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without env passthrough in the triplet ENV{ANDROID_API_LEVEL} will be always empty on windows. So a custom triplet will be necessary anyway and if that is already necessary having a custom specialized toolchain is also not too far away. (I really hate this all purpose android toolchain which includes all possible arches .... )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is why I add the ENV here. The first time I use it, the previous version only set the ANDROID_NATIVE_API_LEVEL with an empty value. I don't know how to fix this.

@Neumann-A
Copy link
Contributor

Again I feel like the default android toolchain vcpkg provides should be removed and replaced with specialized toolchains for each architecture and case. There seems to be a bigger misunderstanding of vcpkg is supposed to work and what work should be done by the configure scripts.

@dg0yt
Copy link
Contributor

dg0yt commented Nov 12, 2021

@holmescn You just closed this PR while I was writing a comment. I actively invited this PR, and I hoped we could help to form an acceptable result, no matter how hard it is to get Android right in vcpkg. I don't see another effort to move things for Android in vcpkg.

@holmesconan
Copy link
Author

holmesconan commented Nov 12, 2021

@dg0yt Thank you for your invitation. Since @Neumann-A made a difficult goal that needs to solve the problem generically. I don't think I have the time and skill to accomplish that target. This is a temporary solution that has many problems unknown. I hope any successor could find more elegant ways to touch the goal, maybe inspired by this effort or not. I would like to give any help if I could.

@holmesconan
Copy link
Author

As a generic solution, we need to consider from scratch that how vcpkg passthrough each detected variable down to the build system and why they are not catched by the Android NDK toolchain. It needs more knowledge about how vcpkg works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category:community-triplet A PR or issue related to community triplets not officially validated by the vcpkg team. category:tool-update The issue is with build tool or build script, which requires update or should be executed correctly requires:vcpkg-team-review This PR or issue requires someone on the vcpkg team to take a further look.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants