| // Copyright 2016 The Bazel Authors. All rights reserved. |
| // |
| // 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. |
| |
| package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools; |
| |
| import com.google.common.collect.ImmutableListMultimap; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Iterables; |
| import com.google.devtools.build.lib.events.Event; |
| import com.google.devtools.build.lib.events.EventHandler; |
| |
| /** |
| * Base class for NDK revision specific {@code ApiLevel}s that encapsulates NDK information about |
| * api level to architecture mappings and api level equivalences. |
| */ |
| public class ApiLevel { |
| /** |
| * Maps an Android API level to the architectures that that level supports. |
| * Based on the directories in the "platforms" directory in the NDK. |
| */ |
| private final ImmutableListMultimap<String, String> apiLevelToArchitectures; |
| |
| /** |
| * Maps an API level to its equivalent API level in the NDK. |
| */ |
| private final ImmutableMap<String, String> apiEquivalencies; |
| |
| private final String correctedApiLevel; |
| |
| protected ApiLevel( |
| ImmutableListMultimap<String, String> apiLevelToArchitectures, |
| ImmutableMap<String, String> apiEquivalencies, |
| EventHandler eventHandler, |
| String repositoryName, |
| String apiLevel) { |
| |
| this.apiLevelToArchitectures = apiLevelToArchitectures; |
| this.apiEquivalencies = apiEquivalencies; |
| this.correctedApiLevel = getCorrectedApiLevel(eventHandler, repositoryName, apiLevel); |
| } |
| |
| /** |
| * Translates the given API level to the equivalent API level in the NDK. |
| */ |
| private String getCorrectedApiLevel( |
| EventHandler eventHandler, String repositoryName, String apiLevel) { |
| |
| String correctedApiLevel = apiEquivalencies.get(apiLevel); |
| if (correctedApiLevel == null) { |
| // The user specified an API level we don't know about. Default to the most recent API level. |
| // This relies on the entries being added in sorted order. |
| String latestApiLevel = Iterables.getLast(apiEquivalencies.keySet()); |
| correctedApiLevel = apiEquivalencies.get(latestApiLevel); |
| |
| eventHandler.handle(Event.warn(String.format( |
| "API level %s specified by android_ndk_repository '%s' is not available. " |
| + "Using latest known API level %s", |
| apiLevel, repositoryName, latestApiLevel))); |
| } |
| return correctedApiLevel; |
| } |
| |
| String getCpuCorrectedApiLevel(String targetCpu) { |
| |
| // Check that this API level supports the given cpu architecture (eg 64 bit is supported on only |
| // 21+). |
| if (!apiLevelToArchitectures.containsEntry(correctedApiLevel, targetCpu)) { |
| // If the given API level does not support the given architecture, find an API level that |
| // does support this architecture. A warning isn't printed because the crosstools for |
| // architectures that aren't supported by this API level are generated anyway, even if the |
| // user doesn't intend to use them (eg, if they're building for only 32 bit archs, the |
| // crosstools for the 64 bit toolchains are generated regardless). |
| // API_LEVEL_TO_ARCHITECTURES.inverse() returns a map of architectures to the APIs that |
| // support that architecture. |
| return Iterables.getLast(apiLevelToArchitectures.inverse().get(targetCpu)); |
| } |
| |
| return correctedApiLevel; |
| } |
| } |
| |