blob: 4fe66c293d68af68fc8f581d64bbb4bb676d5c6b [file] [log] [blame]
// 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;
}
}