microsoft / vcpkg

C++ Library Manager for Windows, Linux, and MacOS
MIT License
23.31k stars 6.44k forks source link

Provide a way to specify Android API Level in default android triplet #41895

Open Deishelon opened 3 weeks ago

Deishelon commented 3 weeks ago

Describe the bug Say you are building for Android, vcpkg provides an out of the box triplets for Android (great!), However, from what I can see there is no way to set API Level.

Each NDK version has it's own 'min' API level, which is what NDK will be using, unless user specifies another value.

With NDK CMake this is done via ANDROID_PLATFORM variable. Documentation: https://developer.android.com/ndk/guides/cmake#android_platform

For example, for NDK 28 (found in ~/Android/Sdk/ndk/28.0.12433566/meta/platforms.json):

  "min": 21,
  "max": 35,

So, by default if you are using NDK 28 with vcpkg and compiling for Android, you will default to 21 API level.

But there are some cases, where you want to change the API level to a higher number.

For example, building openssl with API level 21 will result in an error:

../src/nssl-3.3.2-515f0a0017.clean/providers/implementations/rands/seeding/rand_unix.c:360:9: error: 'getentropy' is unavailable: introduced in Android 28

So, a function getentropy is not there on 21 but there on 28. Hence, you need to tell NDK to compile for android-28.

I didn't find an obvious way to pass my parameter but to copy the official triplet, and use overlay with exact same content, but additional argument like so: Image

The highlighted bit is what I've added to the copied official triplet.

So, suggestion, can we have a way to pass additional args (such as ANDROID_PLATFORM) to triplet? This would avoid users to copy the official triplets modify/add a tiny bit and use overlay.

If it helps, we are using vcpkg via CMake, eg:

.....
include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
dg0yt commented 3 weeks ago

In the triplet file, set VCPKG_CMAKE_SYSTEM_VERSION.

dg0yt commented 3 weeks ago

The API level changes the ABI of the binary artifacts. Thus using a modified triplet is the right way to ensure unambiguous ABI hashes for vcpkg's binary caching.

Deishelon commented 3 weeks ago

Yup, adding set(VCPKG_CMAKE_SYSTEM_VERSION "android-28") into the overlay triplet instead of -DANDROID_PLATFORM=android-28 (as shown in the issue) also works.

Is there any difference why go for one or another? Both seem to do the same thing, unless VCPKG_CMAKE_SYSTEM_VERSION is better for vcpkg internals somehow?

Yup, it make sense from hashes/caches of vcpkg POV, but from user POV, if you need to alter ANDROID_PLATFORM you have to go custom triplet route. Is this something we can improve ?

dg0yt commented 3 weeks ago

Actually I suggest:

set(VCPKG_CMAKE_SYSTEM_VERSION 28)

It is important to understand that the triplet has a central role in ensuring a consistent install tree with regard to binary compatibility. Customizing the file is a reasonable thing with regard to API level.

It is useful to understand that vcpkg uses two modes of CMake when building ports. https://learn.microsoft.com/en-us/vcpkg/contributing/maintainer-guide#portfiles-are-run-in-script-mode

In script mode, the usual variables from toolchains and project() are not available. Some cmake variables variables will control how vcpkg configure CMake projects and toolchains. The triplet file is the key file to control script mode variable. VCPKG_CMAKE_SYSTEM_VERSION is such a variable. So setting this variable to ensure consistent information in script mode and in project mode.

There is a command line option which allows to inject variables into script mode: --cmake-args. I sometimes uses it to quickly test different API levels with the default android triplet. But I wouldn't recommend it for daily use due to ABI hashing.

Deishelon commented 2 weeks ago

Thanks for detailed explanation!

My only remark would be, I know VCPKG_CMAKE_SYSTEM_VERSION is documented on its own, but as a user you kinda have to know this variable exists, and how to use it.

If someone just poking around: https://learn.microsoft.com/en-us/vcpkg/users/platforms/android docs - there is nothing mention about this.

Do you think we can make some improvements to the documentation? Mainly I'm thinking:

dg0yt commented 2 weeks ago

You can add your suggestion directly in a PR to https://github.com/microsoft/vcpkg-docs/.