com.android.builder.internal.compiler.RenderScriptProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2013 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.builder.internal.compiler;
import static com.android.SdkConstants.EXT_BC;
import static com.android.SdkConstants.FN_RENDERSCRIPT_V8_JAR;
import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.internal.LoggedErrorException;
import com.android.ide.common.internal.WaitableExecutor;
import com.android.ide.common.process.ProcessException;
import com.android.ide.common.process.ProcessExecutor;
import com.android.ide.common.process.ProcessInfoBuilder;
import com.android.ide.common.process.ProcessOutputHandler;
import com.android.ide.common.process.ProcessResult;
import com.android.sdklib.BuildToolInfo;
import com.google.common.collect.Maps;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* Compiles Renderscript files.
*/
public class RenderScriptProcessor {
// ABI list, as pairs of (android-ABI, toolchain-ABI)
private static final class Abi {
@NonNull
private final String mDevice;
@NonNull
private final String mToolchain;
@NonNull
private final BuildToolInfo.PathId mLinker;
@NonNull
private final String[] mLinkerArgs;
Abi(@NonNull String device,
@NonNull String toolchain,
@NonNull BuildToolInfo.PathId linker,
@NonNull String... linkerArgs) {
mDevice = device;
mToolchain = toolchain;
mLinker = linker;
mLinkerArgs = linkerArgs;
}
}
private static final Abi[] ABIS = {
new Abi("armeabi-v7a", "armv7-none-linux-gnueabi", BuildToolInfo.PathId.LD_ARM,
"-dynamic-linker", "/system/bin/linker", "-X", "-m", "armelf_linux_eabi"),
new Abi("mips", "mipsel-unknown-linux", BuildToolInfo.PathId.LD_MIPS, "-EL"),
new Abi("x86", "i686-unknown-linux", BuildToolInfo.PathId.LD_X86, "-m", "elf_i386") };
public static final String RS_DEPS = "rsDeps";
@NonNull
private final List mSourceFolders;
@NonNull
private final List mImportFolders;
@NonNull
private final File mSourceOutputDir;
@NonNull
private final File mResOutputDir;
@NonNull
private final File mObjOutputDir;
@NonNull
private final File mLibOutputDir;
@NonNull
private final BuildToolInfo mBuildToolInfo;
private final int mTargetApi;
private final boolean mDebugBuild;
private final int mOptimLevel;
private final boolean mNdkMode;
private final boolean mSupportMode;
private final Set mAbiFilters;
private final File mRsLib;
private final Map mLibClCore = Maps.newHashMap();
public RenderScriptProcessor(
@NonNull List sourceFolders,
@NonNull List importFolders,
@NonNull File sourceOutputDir,
@NonNull File resOutputDir,
@NonNull File objOutputDir,
@NonNull File libOutputDir,
@NonNull BuildToolInfo buildToolInfo,
int targetApi,
boolean debugBuild,
int optimLevel,
boolean ndkMode,
boolean supportMode,
@Nullable Set abiFilters) {
mSourceFolders = sourceFolders;
mImportFolders = importFolders;
mSourceOutputDir = sourceOutputDir;
mResOutputDir = resOutputDir;
mObjOutputDir = objOutputDir;
mLibOutputDir = libOutputDir;
mBuildToolInfo = buildToolInfo;
mTargetApi = targetApi;
mDebugBuild = debugBuild;
mOptimLevel = optimLevel;
mNdkMode = ndkMode;
mSupportMode = supportMode;
mAbiFilters = abiFilters;
if (supportMode) {
File rs = new File(mBuildToolInfo.getLocation(), "renderscript");
mRsLib = new File(rs, "lib");
File bcFolder = new File(mRsLib, "bc");
for (Abi abi : ABIS) {
mLibClCore.put(abi.mDevice,
new File(bcFolder, abi.mDevice + File.separatorChar + "libclcore.bc"));
}
} else {
mRsLib = null;
}
}
public static File getSupportJar(String buildToolsFolder) {
return new File(buildToolsFolder, "renderscript/lib/" + FN_RENDERSCRIPT_V8_JAR);
}
public static File getSupportNativeLibFolder(String buildToolsFolder) {
File rs = new File(buildToolsFolder, "renderscript");
File lib = new File(rs, "lib");
return new File(lib, "packaged");
}
public void build(
@NonNull ProcessExecutor processExecutor,
@NonNull ProcessOutputHandler processOutputHandler)
throws InterruptedException, ProcessException, LoggedErrorException, IOException {
// gather the files to compile
FileGatherer fileGatherer = new FileGatherer();
SourceSearcher searcher = new SourceSearcher(mSourceFolders, "rs", "fs");
searcher.setUseExecutor(false);
searcher.search(fileGatherer);
List renderscriptFiles = fileGatherer.getFiles();
if (renderscriptFiles.isEmpty()) {
return;
}
// get the env var
Map env = Maps.newHashMap();
if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
env.put("DYLD_LIBRARY_PATH", mBuildToolInfo.getLocation().getAbsolutePath());
} else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
env.put("LD_LIBRARY_PATH", mBuildToolInfo.getLocation().getAbsolutePath());
}
doMainCompilation(renderscriptFiles, processExecutor, processOutputHandler, env);
if (mSupportMode) {
createSupportFiles(processExecutor, processOutputHandler, env);
}
}
private void doMainCompilation(
@NonNull List inputFiles,
@NonNull ProcessExecutor processExecutor,
@NonNull ProcessOutputHandler processOutputHandler,
@NonNull Map env)
throws ProcessException {
ProcessInfoBuilder builder = new ProcessInfoBuilder();
String renderscript = mBuildToolInfo.getPath(BuildToolInfo.PathId.LLVM_RS_CC);
if (renderscript == null || !new File(renderscript).isFile()) {
throw new IllegalStateException(BuildToolInfo.PathId.LLVM_RS_CC + " is missing");
}
String rsPath = mBuildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS);
String rsClangPath = mBuildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS_CLANG);
// the renderscript compiler doesn't expect the top res folder,
// but the raw folder directly.
File rawFolder = new File(mResOutputDir, SdkConstants.FD_RES_RAW);
// compile all the files in a single pass
builder.setExecutable(renderscript);
builder.addEnvironments(env);
// Due to a device side bug, let's not enable this at this time.
// if (mDebugBuild) {
// command.add("-g");
// }
builder.addArgs("-O");
builder.addArgs(Integer.toString(mOptimLevel));
// add all import paths
builder.addArgs("-I");
builder.addArgs(rsPath);
builder.addArgs("-I");
builder.addArgs(rsClangPath);
for (File importPath : mImportFolders) {
if (importPath.isDirectory()) {
builder.addArgs("-I");
builder.addArgs(importPath.getAbsolutePath());
}
}
if (mSupportMode) {
builder.addArgs("-rs-package-name=android.support.v8.renderscript");
}
// source output
builder.addArgs("-p");
builder.addArgs(mSourceOutputDir.getAbsolutePath());
if (mNdkMode) {
builder.addArgs("-reflect-c++");
}
// res output
builder.addArgs("-o");
builder.addArgs(rawFolder.getAbsolutePath());
builder.addArgs("-target-api");
int targetApi = mTargetApi < 11 ? 11 : mTargetApi;
targetApi = (mSupportMode && targetApi < 18) ? 18 : targetApi;
builder.addArgs(Integer.toString(targetApi));
// input files
for (File sourceFile : inputFiles) {
builder.addArgs(sourceFile.getAbsolutePath());
}
ProcessResult result = processExecutor.execute(
builder.createProcess(), processOutputHandler);
result.rethrowFailure().assertNormalExitValue();
}
private void createSupportFiles(
@NonNull final ProcessExecutor processExecutor,
@NonNull final ProcessOutputHandler processOutputHandler,
@NonNull final Map env)
throws IOException, InterruptedException, LoggedErrorException, ProcessException {
// get the generated BC files.
File rawFolder = new File(mResOutputDir, SdkConstants.FD_RES_RAW);
SourceSearcher searcher = new SourceSearcher(
Collections.singletonList(rawFolder), EXT_BC);
FileGatherer fileGatherer = new FileGatherer();
searcher.search(fileGatherer);
WaitableExecutor mExecutor = new WaitableExecutor();
for (final File bcFile : fileGatherer.getFiles()) {
String name = bcFile.getName();
final String objName = name.replaceAll("\\.bc", ".o");
final String soName = "librs." + name.replaceAll("\\.bc", ".so");
for (final Abi abi : ABIS) {
if (mAbiFilters != null && !mAbiFilters.contains(abi.mDevice)) {
continue;
}
// make sure the dest folders exist
final File objAbiFolder = new File(mObjOutputDir, abi.mDevice);
if (!objAbiFolder.isDirectory() && !objAbiFolder.mkdirs()) {
throw new IOException("Unable to create dir " + objAbiFolder.getAbsolutePath());
}
final File libAbiFolder = new File(mLibOutputDir, abi.mDevice);
if (!libAbiFolder.isDirectory() && !libAbiFolder.mkdirs()) {
throw new IOException("Unable to create dir " + libAbiFolder.getAbsolutePath());
}
mExecutor.execute(new Callable() {
@Override
public Void call() throws Exception {
File objFile = createSupportObjFile(
bcFile,
abi,
objName,
objAbiFolder,
processExecutor,
processOutputHandler,
env);
createSupportLibFile(
objFile,
abi,
soName,
libAbiFolder,
processExecutor,
processOutputHandler,
env);
return null;
}
});
}
}
mExecutor.waitForTasksWithQuickFail(true /*cancelRemaining*/);
}
private File createSupportObjFile(
@NonNull File bcFile,
@NonNull Abi abi,
@NonNull String objName,
@NonNull File objAbiFolder,
@NonNull ProcessExecutor processExecutor,
@NonNull ProcessOutputHandler processOutputHandler,
@NonNull Map env) throws ProcessException {
ProcessInfoBuilder builder = new ProcessInfoBuilder();
builder.setExecutable(mBuildToolInfo.getPath(BuildToolInfo.PathId.BCC_COMPAT));
builder.addEnvironments(env);
builder.addArgs("-O" + Integer.toString(mOptimLevel));
File outFile = new File(objAbiFolder, objName);
builder.addArgs("-o", outFile.getAbsolutePath());
builder.addArgs("-fPIC");
builder.addArgs("-shared");
builder.addArgs("-rt-path", mLibClCore.get(abi.mDevice).getAbsolutePath());
builder.addArgs("-mtriple", abi.mToolchain);
builder.addArgs(bcFile.getAbsolutePath());
processExecutor.execute(
builder.createProcess(), processOutputHandler)
.rethrowFailure().assertNormalExitValue();
return outFile;
}
private void createSupportLibFile(
@NonNull File objFile,
@NonNull Abi abi,
@NonNull String soName,
@NonNull File libAbiFolder,
@NonNull ProcessExecutor processExecutor,
@NonNull ProcessOutputHandler processOutputHandler,
@NonNull Map env) throws ProcessException {
File intermediatesFolder = new File(mRsLib, "intermediates");
File intermediatesAbiFolder = new File(intermediatesFolder, abi.mDevice);
File packagedFolder = new File(mRsLib, "packaged");
File packagedAbiFolder = new File(packagedFolder, abi.mDevice);
ProcessInfoBuilder builder = new ProcessInfoBuilder();
builder.setExecutable(mBuildToolInfo.getPath(abi.mLinker));
builder.addEnvironments(env);
builder.addArgs("--eh-frame-hdr")
.addArgs(abi.mLinkerArgs)
.addArgs("-shared", "-Bsymbolic", "-z", "noexecstack", "-z", "relro", "-z", "now");
File outFile = new File(libAbiFolder, soName);
builder.addArgs("-o", outFile.getAbsolutePath());
builder.addArgs(
"-L" + intermediatesAbiFolder.getAbsolutePath(),
"-L" + packagedAbiFolder.getAbsolutePath(),
"-soname",
soName,
objFile.getAbsolutePath(),
new File(intermediatesAbiFolder, "libcompiler_rt.a").getAbsolutePath(),
"-lRSSupport",
"-lm",
"-lc");
processExecutor.execute(
builder.createProcess(), processOutputHandler)
.rethrowFailure().assertNormalExitValue();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy