From 9c63e7b7163ac3e41148eba7ee14bf3575e12f67 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 13 Aug 2021 14:26:25 -0700 Subject: [PATCH] Fix API clamping in the new CMake toolchain. Test: added test Bug: https://github.com/android/ndk/issues/1560 Change-Id: If5fbba07e1c3630ef1b2766c684288ca07294ff6 (cherry picked from commit 29519e933943722de6061b940f17fa0bbe9e8e82) --- build/cmake/adjust_api_level.cmake | 63 +++++++++++++++++++ build/cmake/android.toolchain.cmake | 31 +-------- docs/changelogs/Changelog-r23.md | 5 ++ tests/build/cmake_api_pull_up/__init__.py | 0 .../cmake_api_pull_up/project/CMakeLists.txt | 4 ++ tests/build/cmake_api_pull_up/project/foo.cpp | 3 + tests/build/cmake_api_pull_up/test.py | 48 ++++++++++++++ tests/build/cmake_api_pull_up/test_config.py | 10 +++ 8 files changed, 136 insertions(+), 28 deletions(-) create mode 100644 build/cmake/adjust_api_level.cmake create mode 100644 tests/build/cmake_api_pull_up/__init__.py create mode 100644 tests/build/cmake_api_pull_up/project/CMakeLists.txt create mode 100644 tests/build/cmake_api_pull_up/project/foo.cpp create mode 100644 tests/build/cmake_api_pull_up/test.py create mode 100644 tests/build/cmake_api_pull_up/test_config.py diff --git a/build/cmake/adjust_api_level.cmake b/build/cmake/adjust_api_level.cmake new file mode 100644 index 00000000..780d76c8 --- /dev/null +++ b/build/cmake/adjust_api_level.cmake @@ -0,0 +1,63 @@ +include(${CMAKE_ANDROID_NDK}/build/cmake/platforms.cmake) + +function(adjust_api_level api_level result_name) + # If no platform version was chosen by the user, default to the minimum + # version supported by this NDK. + if(NOT api_level) + message(STATUS + "ANDROID_PLATFORM not set. Defaulting to minimum supported version " + "${NDK_MIN_PLATFORM_LEVEL}.") + + set(api_level "android-${NDK_MIN_PLATFORM_LEVEL}") + endif() + + if(api_level STREQUAL "latest") + message(STATUS + "Using latest available ANDROID_PLATFORM: ${NDK_MAX_PLATFORM_LEVEL}.") + set(api_level "android-${NDK_MAX_PLATFORM_LEVEL}") + endif() + + string(REPLACE "android-" "" result ${api_level}) + + # Aliases defined by meta/platforms.json include codename aliases for platform + # API levels as well as cover any gaps in platforms that may not have had NDK + # APIs. + if(NOT "${NDK_PLATFORM_ALIAS_${result}}" STREQUAL "") + message(STATUS + "${api_level} is an alias for ${NDK_PLATFORM_ALIAS_${result}}. Adjusting " + "ANDROID_PLATFORM to match.") + set(api_level "${NDK_PLATFORM_ALIAS_${result}}") + string(REPLACE "android-" "" result ${api_level}) + endif() + + # Pull up to the minimum supported version if an old API level was requested. + if(result LESS NDK_MIN_PLATFORM_LEVEL) + message(STATUS + "${api_level} is unsupported. Using minimum supported version " + "${NDK_MIN_PLATFORM_LEVEL}.") + set(api_level "android-${NDK_MIN_PLATFORM_LEVEL}") + string(REPLACE "android-" "" result ${api_level}) + endif() + + # And for LP64 we need to pull up to 21. No diagnostic is provided here + # because minSdkVersion < 21 is valid for the project even though it may not + # be for this ABI. + if(ANDROID_ABI MATCHES "64(-v8a)?$" AND result LESS 21) + message(STATUS + "android-${result} is not supported for ${ANDROID_ABI}. Using minimum " + "supported LP64 version 21.") + set(api_level android-21) + set(result 21) + endif() + + # ANDROID_PLATFORM beyond the maximum is an error. The correct way to specify + # the latest version is ANDROID_PLATFORM=latest. + if(result GREATER NDK_MAX_PLATFORM_LEVEL) + message(SEND_ERROR + "${api_level} is above the maximum supported version " + "${NDK_MAX_PLATFORM_LEVEL}. Choose a supported API level or set " + "ANDROID_PLATFORM to \"latest\".") + endif() + + set(${result_name} ${result} PARENT_SCOPE) +endfunction() diff --git a/build/cmake/android.toolchain.cmake b/build/cmake/android.toolchain.cmake index f56333b7..119e66b2 100644 --- a/build/cmake/android.toolchain.cmake +++ b/build/cmake/android.toolchain.cmake @@ -166,34 +166,9 @@ elseif(ANDROID_TOOLCHAIN STREQUAL gcc) "https://android.googlesource.com/platform/ndk/+/master/docs/ClangMigration.md.") endif() -include(${CMAKE_ANDROID_NDK}/build/cmake/platforms.cmake) - -if(ANDROID_NATIVE_API_LEVEL AND NOT ANDROID_PLATFORM) - if(ANDROID_NATIVE_API_LEVEL MATCHES "^android-[0-9]+$") - set(ANDROID_PLATFORM ${ANDROID_NATIVE_API_LEVEL}) - elseif(ANDROID_NATIVE_API_LEVEL MATCHES "^[0-9]+$") - set(ANDROID_PLATFORM android-${ANDROID_NATIVE_API_LEVEL}) - endif() -endif() -if(NOT CMAKE_SYSTEM_VERSION AND ANDROID_PLATFORM) - if(ANDROID_PLATFORM STREQUAL "latest") - message(STATUS - "Using latest available ANDROID_PLATFORM: ${NDK_MAX_PLATFORM_LEVEL}.") - set(CMAKE_SYSTEM_VERSION "${NDK_MAX_PLATFORM_LEVEL}") - else() - string(REPLACE "android-" "" CMAKE_SYSTEM_VERSION ${ANDROID_PLATFORM}) - # Aliases defined by meta/platforms.json include codename aliases for platform - # API levels as well as cover any gaps in platforms that may not have had NDK - # APIs. - if(NOT "${NDK_PLATFORM_ALIAS_${CMAKE_SYSTEM_VERSION}}" STREQUAL "") - message(STATUS "\ - ${CMAKE_SYSTEM_VERSION} is an alias for \ - ${NDK_PLATFORM_ALIAS_${CMAKE_SYSTEM_VERSION}}.") - string(REPLACE "android-" "" CMAKE_SYSTEM_VERSION - "${NDK_PLATFORM_ALIAS_${CMAKE_SYSTEM_VERSION}}") - endif() - endif() -endif() +include(${CMAKE_ANDROID_NDK}/build/cmake/adjust_api_level.cmake) +adjust_api_level(${ANDROID_PLATFORM} CMAKE_SYSTEM_VERSION) +message(STATUS "CMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") if(NOT DEFINED CMAKE_ANDROID_STL_TYPE AND DEFINED ANDROID_STL) set(CMAKE_ANDROID_STL_TYPE ${ANDROID_STL}) diff --git a/docs/changelogs/Changelog-r23.md b/docs/changelogs/Changelog-r23.md index d0f930d7..bfb8142a 100644 --- a/docs/changelogs/Changelog-r23.md +++ b/docs/changelogs/Changelog-r23.md @@ -30,9 +30,14 @@ For Android Studio issues, follow the docs on the [Android Studio site]. ## r23b +* [Issue 1560]: Fixed pull-up of unsupported API levels when using the new CMake + toolchain file. This affects CMake 3.21 and + `ANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON` use cases, and was the common case for + AGP users with a `minSdkVersion` below 21. * [Issue 1573]: Fixed `ANDROID_USE_LEGACY_TOOLCHAIN_FILE` not being obeyed during CMake try-compile. +[Issue 1560]: https://github.com/android/ndk/issues/1560 [Issue 1573]: https://github.com/android/ndk/issues/1573 ## Changes diff --git a/tests/build/cmake_api_pull_up/__init__.py b/tests/build/cmake_api_pull_up/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/build/cmake_api_pull_up/project/CMakeLists.txt b/tests/build/cmake_api_pull_up/project/CMakeLists.txt new file mode 100644 index 00000000..ddcd3536 --- /dev/null +++ b/tests/build/cmake_api_pull_up/project/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.6) +project(ApiLevelPullUpTest CXX) + +add_library(foo SHARED foo.cpp) diff --git a/tests/build/cmake_api_pull_up/project/foo.cpp b/tests/build/cmake_api_pull_up/project/foo.cpp new file mode 100644 index 00000000..b876b5c8 --- /dev/null +++ b/tests/build/cmake_api_pull_up/project/foo.cpp @@ -0,0 +1,3 @@ +#if __ANDROID_API__ != 21 +#error API level was not pulled up to 21 +#endif diff --git a/tests/build/cmake_api_pull_up/test.py b/tests/build/cmake_api_pull_up/test.py new file mode 100644 index 00000000..c1c8be8b --- /dev/null +++ b/tests/build/cmake_api_pull_up/test.py @@ -0,0 +1,48 @@ +# +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Check that pre-LP64 API levels are correctly pulled-up for CMake.""" +from pathlib import Path +import subprocess + +from ndk.cmake import find_cmake, find_ninja +from ndk.test.spec import BuildConfiguration, CMakeToolchainFile + + +def run_test(ndk_path: str, config: BuildConfiguration) -> tuple[bool, str]: + """Check that pre-LP64 API levels are correctly pulled-up for CMake.""" + cmake = find_cmake() + ninja = find_ninja() + toolchain_path = Path(ndk_path) / 'build/cmake/android.toolchain.cmake' + project_path = 'project' + if config.toolchain_file is CMakeToolchainFile.Legacy: + toolchain_mode = 'ON' + else: + toolchain_mode = 'OFF' + cmake_cmd = [ + str(cmake), + f'-DCMAKE_TOOLCHAIN_FILE={toolchain_path}', + f'-DANDROID_ABI={config.abi}', + '-DANDROID_PLATFORM=android-19', + f'-DCMAKE_MAKE_PROGRAM={ninja}', + f'-DANDROID_USE_LEGACY_TOOLCHAIN_FILE={toolchain_mode}', + '-GNinja', + ] + result = subprocess.run(cmake_cmd, + check=False, + cwd=project_path, + capture_output=True, + text=True) + return result.returncode == 0, result.stdout diff --git a/tests/build/cmake_api_pull_up/test_config.py b/tests/build/cmake_api_pull_up/test_config.py new file mode 100644 index 00000000..aa58ee59 --- /dev/null +++ b/tests/build/cmake_api_pull_up/test_config.py @@ -0,0 +1,10 @@ +from typing import Optional + +from ndk.abis import LP32_ABIS +from ndk.test.types import Test + + +def build_unsupported(test: Test) -> Optional[str]: + if test.config.abi in LP32_ABIS: + return test.config.abi + return None