
com.android.build.gradle.ndk.internal.NdkHandler Maven / Gradle / Ivy
/*
* Copyright (C) 2014 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.
*/
package com.android.build.gradle.ndk.internal;
import static com.android.SdkConstants.FN_LOCAL_PROPERTIES;
import com.android.SdkConstants;
import com.android.annotations.Nullable;
import com.android.build.gradle.ndk.NdkExtension;
import com.android.builder.model.AndroidProject;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Closeables;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project;
import org.gradle.nativebinaries.BuildType;
import org.gradle.nativebinaries.platform.Platform;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Locale;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Handles NDK related information.
*/
public class NdkHandler {
// Map of ABI to toolchain platform string.
private static final Map PLATFORM_STRING;
// Map of ABI to target architecture
private static final Map ARCHITECTURE_STRING;
// Map of toolchain names to the subdirectory name containing the toolchain.
private static final Map TOOLCHAIN_STRING;
private static final List ABI32 = ImmutableList.of(
SdkConstants.ABI_INTEL_ATOM,
SdkConstants.ABI_ARMEABI_V7A,
SdkConstants.ABI_ARMEABI,
SdkConstants.ABI_MIPS);
private static final List ALL_ABI = ImmutableList.of(
SdkConstants.ABI_INTEL_ATOM,
SdkConstants.ABI_INTEL_ATOM64,
SdkConstants.ABI_ARMEABI_V7A,
SdkConstants.ABI_ARMEABI,
SdkConstants.ABI_ARM64_V8A,
SdkConstants.ABI_MIPS,
SdkConstants.ABI_MIPS64);
private NdkExtension ndkExtension;
private Project project;
private File ndkDirectory;
static {
// Initialize static maps.
PLATFORM_STRING = ImmutableMap.builder()
.put(SdkConstants.ABI_INTEL_ATOM, "x86")
.put(SdkConstants.ABI_INTEL_ATOM64, "x86_64")
.put(SdkConstants.ABI_ARMEABI_V7A, "arm-linux-androideabi")
.put(SdkConstants.ABI_ARMEABI, "arm-linux-androideabi")
.put(SdkConstants.ABI_ARM64_V8A, "aarch64-linux-android")
.put(SdkConstants.ABI_MIPS, "mipsel-linux-android")
.put(SdkConstants.ABI_MIPS64, "mips64el-linux-android")
.build();
ARCHITECTURE_STRING = ImmutableMap.builder()
.put(SdkConstants.ABI_INTEL_ATOM, SdkConstants.CPU_ARCH_INTEL_ATOM)
.put(SdkConstants.ABI_INTEL_ATOM64, SdkConstants.CPU_ARCH_INTEL_ATOM64)
.put(SdkConstants.ABI_ARMEABI_V7A, SdkConstants.CPU_ARCH_ARM)
.put(SdkConstants.ABI_ARMEABI, SdkConstants.CPU_ARCH_ARM)
.put(SdkConstants.ABI_ARM64_V8A, SdkConstants.CPU_ARCH_ARM64)
.put(SdkConstants.ABI_MIPS, SdkConstants.CPU_ARCH_MIPS)
.put(SdkConstants.ABI_MIPS64, SdkConstants.CPU_ARCH_MIPS64)
.build();
TOOLCHAIN_STRING = ImmutableMap.builder()
.put("gcc", "")
.put("clang", "clang")
.build();
}
public NdkHandler(Project project, NdkExtension ndkExtension) {
this.project = project;
this.ndkExtension = ndkExtension;
ndkDirectory = findNdkDirectory(project);
}
/**
* Toolchain name used by the NDK.
*
* This is the name of the folder containing the toolchain under $ANDROID_NDK_HOME/toolchain.
* e.g. for gcc targetting arm64_v8a, this method returns "aarch64-linux-android-4.9".
*/
private static String getToolchainName(
String toolchain,
String toolchainVersion,
String platform) {
return PLATFORM_STRING.get(platform) + "-" + TOOLCHAIN_STRING.get(toolchain)
+ toolchainVersion;
}
/**
* Determine the location of the NDK directory.
*
* The NDK directory can be set in the local.properties file or using the ANDROID_NDK_HOME
* environment variable.
*/
private static File findNdkDirectory(Project project) {
File rootDir = project.getRootDir();
File localProperties = new File(rootDir, FN_LOCAL_PROPERTIES);
if (localProperties.isFile()) {
Properties properties = new Properties();
InputStreamReader reader = null;
try {
//noinspection IOResourceOpenedButNotSafelyClosed
FileInputStream fis = new FileInputStream(localProperties);
reader = new InputStreamReader(fis, Charsets.UTF_8);
properties.load(reader);
} catch (FileNotFoundException ignored) {
// ignore since we check up front and we don't want to fail on it anyway
// in case there's an env var.
} catch (IOException e) {
throw new RuntimeException("Unable to read ${localProperties}", e);
} finally {
try {
Closeables.close(reader, true /* swallowIOException */);
} catch (IOException e) {
// ignore.
}
}
String ndkDirProp = properties.getProperty("ndk.dir");
if (ndkDirProp != null) {
return new File(ndkDirProp);
}
} else {
String envVar = System.getenv("ANDROID_NDK_HOME");
if (envVar != null) {
return new File(envVar);
}
}
return null;
}
/**
* Returns the directory of the NDK.
*/
@Nullable
public File getNdkDirectory() {
return ndkDirectory;
}
NdkExtension getNdkExtension() {
return ndkExtension;
}
/**
* Return the path containing the prebuilt toolchain.
*
* @param toolchain Name of the toolchain ["gcc", "clang"].
* @param toolchainVersion Version of the toolchain.
* @param platform Target platform supported by the NDK.
* @return Directory containing the prebuilt toolchain.
*/
public File getToolchainPath(String toolchain, String toolchainVersion, String platform) {
File prebuiltFolder;
if (toolchain.equals("gcc")) {
prebuiltFolder = new File(
getNdkDirectory(),
"toolchains/" + getToolchainName(toolchain, toolchainVersion, platform)
+ "/prebuilt");
} else if (toolchain.equals("clang")) {
prebuiltFolder = new File(
getNdkDirectory(),
"toolchains/llvm-" + toolchainVersion + "/prebuilt");
} else {
throw new InvalidUserDataException("Unrecognized toolchain: " + toolchain);
}
String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
String hostOs;
if (osName.contains("windows")) {
hostOs = "windows";
} else if (osName.contains("mac")) {
hostOs = "darwin";
} else {
hostOs = "linux";
}
// Use 64-bit toolchain if available.
File toolchainPath = new File(prebuiltFolder, hostOs + "-x86_64");
if (toolchainPath.isDirectory()) {
return toolchainPath;
}
// Fallback to 32-bit if we can't find the 64-bit toolchain.
toolchainPath = new File(prebuiltFolder, hostOs);
if (toolchainPath.isDirectory()) {
return toolchainPath;
} else {
throw new InvalidUserDataException("Unable to find toolchain prebuilt folder in: "
+ prebuiltFolder);
}
}
/**
* Returns the sysroot directory for the toolchain.
*/
public String getSysroot(Platform platform) {
return ndkDirectory + "/platforms/" + ndkExtension.getCompileSdkVersion()
+ "/arch-" + ARCHITECTURE_STRING.get(platform.getName());
}
/**
* Return the output directory for a BuildType and Platform.
*/
public File getOutputDirectory(BuildType buildType, Platform platform) {
return new File(
project.getBuildDir() + "/" + AndroidProject.FD_INTERMEDIATES + "/binaries/",
ndkExtension.getModuleName() + "SharedLibrary/" + buildType.getName() + "/lib/" +
platform.getName());
}
/**
* Return the directory containing prebuilt binaries such as gdbserver.
*/
public File getPrebuiltDirectory(Platform platform) {
return new File(
ndkDirectory, "prebuilt/android-" + ARCHITECTURE_STRING.get(platform.getName()));
}
/**
* Return true if compiledSdkVersion supports 64 bits ABI.
*/
public boolean supports64Bits() {
String targetString = getNdkExtension().getCompileSdkVersion().replace("android-", "");
try {
return Integer.parseInt(targetString) >= 20;
} catch (NumberFormatException ignored) {
// "android-L" supports 64-bits.
return true;
}
}
/**
* Return the gcc version that will be used by the NDK.
*
* If the gcc toolchain is used, then it's simply the toolchain version requested by the user.
* If clang is used, then it depends on the version of the NDK.
*/
public String getGccToolchainVersion() {
if (ndkExtension.getToolchain().equals("gcc")) {
return ndkExtension.getToolchainVersion();
} else {
return supports64Bits() ? "4.9" : "4.8";
}
}
/**
* Returns a list of supported ABI.
*/
public Collection getSupportedAbis() {
return supports64Bits() ? ALL_ABI : ABI32;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy