Search in sources :

Example 1 with FileCache

use of com.android.builder.utils.FileCache in project atlas by alibaba.

the class AtlasDesugarTransform method processSingle.

private void processSingle(@NonNull Path input, @NonNull Path output, @NonNull Set<? super QualifiedContent.Scope> scopes) throws Exception {
    waitableExecutor.execute(() -> {
        if (output.toString().endsWith(SdkConstants.DOT_JAR)) {
            Files.createDirectories(output.getParent());
        } else {
            Files.createDirectories(output);
        }
        FileCache cacheToUse;
        if (Files.isRegularFile(input) && Objects.equals(scopes, Collections.singleton(QualifiedContent.Scope.EXTERNAL_LIBRARIES))) {
            cacheToUse = userCache;
        } else {
            cacheToUse = null;
        }
        processUsingCache(input, output, cacheToUse);
        return null;
    });
}
Also used : FileCache(com.android.builder.utils.FileCache)

Example 2 with FileCache

use of com.android.builder.utils.FileCache in project atlas by alibaba.

the class AtlasDexArchiveBuilderCacheHander method populateCache.

void populateCache(Multimap<QualifiedContent, File> cacheableItems) throws Exception {
    for (QualifiedContent input : cacheableItems.keys()) {
        FileCache cache = getBuildCache(input.getFile(), isExternalLib(input), userLevelCache);
        if (cache != null) {
            FileCache.Inputs buildCacheInputs = AtlasDexArchiveBuilderCacheHander.getBuildCacheInputs(input.getFile(), dexOptions, dexer, minSdkVersion, isDebuggable);
            FileCache.QueryResult result = cache.createFileInCacheIfAbsent(buildCacheInputs, in -> {
                Collection<File> dexArchives = cacheableItems.get(input);
                logger.verbose("Merging %1$s into %2$s", Joiner.on(',').join(dexArchives), in.getAbsolutePath());
                mergeJars(in, cacheableItems.get(input));
            });
            if (result.getQueryEvent().equals(FileCache.QueryEvent.CORRUPTED)) {
                Verify.verifyNotNull(result.getCauseOfCorruption());
                logger.info("The build cache at '%1$s' contained an invalid cache entry.\n" + "Cause: %2$s\n" + "We have recreated the cache entry.\n" + "%3$s", cache.getCacheDirectory().getAbsolutePath(), Throwables.getStackTraceAsString(result.getCauseOfCorruption()), BuildCacheUtils.BUILD_CACHE_TROUBLESHOOTING_MESSAGE);
            }
        }
    }
}
Also used : QualifiedContent(com.android.build.api.transform.QualifiedContent) JarFile(java.util.jar.JarFile) FileCache(com.android.builder.utils.FileCache)

Example 3 with FileCache

use of com.android.builder.utils.FileCache in project atlas by alibaba.

the class AtlasDexArchiveBuilderCacheHander method getCachedVersionIfPresent.

@Nullable
public File getCachedVersionIfPresent(JarInput input) throws Exception {
    FileCache cache = getBuildCache(input.getFile(), isExternalLib(input), userLevelCache);
    if (cache == null) {
        return null;
    }
    FileCache.Inputs buildCacheInputs = getBuildCacheInputs(input.getFile(), dexOptions, dexer, minSdkVersion, isDebuggable);
    return cache.cacheEntryExists(buildCacheInputs) ? cache.getFileInCache(buildCacheInputs) : null;
}
Also used : FileCache(com.android.builder.utils.FileCache) Nullable(com.android.annotations.Nullable)

Example 4 with FileCache

use of com.android.builder.utils.FileCache in project atlas by alibaba.

the class AtlasMainDexMerger method merge.

public void merge(List<File> mainDexFiles, File outputDir, File[][] mergeDexs) {
    sort(mainDexFiles);
    FileCache.Inputs buildCacheInputs = getBuildCacheInputs(mainDexFiles, dexingType, dexMerger, mainDexListFile == null ? null : mainDexListFile.getSingleFile(), minSdkVersion, isDebuggable, "maindex", ID);
    ProcessOutput output = outputHandler.createOutput();
    FileCache fileCache = BuildCacheUtils.createBuildCacheIfEnabled(variantOutputContext.getVariantContext().getProject(), variantOutputContext.getScope().getGlobalScope().getProjectOptions());
    if (fileCache == null) {
        try {
            fileCache = FileCache.getInstanceWithMultiProcessLocking(new File(AndroidLocation.getFolder(), "atlas-buildCache"));
        } catch (AndroidLocation.AndroidLocationException e) {
            e.printStackTrace();
        }
    }
    if (variantOutputContext.getVariantContext().getAtlasExtension().getTBuildConfig().getMergeBundlesDex()) {
        allDexsArchives.addAll(Arrays.asList(mergeDexs[0]));
        return;
    }
    try {
        FileCache.QueryResult result = fileCache.createFileInCacheIfAbsent(buildCacheInputs, in -> {
            List<ForkJoinTask<Void>> mergeTasks = new ArrayList();
            if (dexingType == DexingType.NATIVE_MULTIDEX) {
                mergeTasks.addAll(handleNativeMultiDex(Arrays.asList(mergeDexs[0]), output, outputDir, mainDexListFile == null ? null : mainDexListFile.getSingleFile()));
            } else {
                mergeTasks.addAll(handleLegacyAndMonoDex(Arrays.asList(mergeDexs[0]), output, outputDir, mainDexListFile == null ? null : mainDexListFile.getSingleFile()));
            }
            mergeTasks.forEach(voidForkJoinTask -> voidForkJoinTask.join());
            cacheHandler.handleMissActionResult(outputDir, in);
            if (output != null) {
                try {
                    outputHandler.handleOutput(output);
                } catch (ProcessException e) {
                // ignore this one
                }
            }
        });
        cacheHandler.handleQueryResult(result, outputDir, "maindex");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Also used : ProcessException(com.android.ide.common.process.ProcessException) ProcessOutput(com.android.ide.common.process.ProcessOutput) ForkJoinTask(java.util.concurrent.ForkJoinTask) ProcessException(com.android.ide.common.process.ProcessException) FileCache(com.android.builder.utils.FileCache) AndroidLocation(com.android.prefs.AndroidLocation)

Example 5 with FileCache

use of com.android.builder.utils.FileCache in project atlas by alibaba.

the class DexByteCodeConverterHook method convertByteCode.

// @Override
// public void runDexer(DexProcessBuilder builder, DexOptions dexOptions, ProcessOutputHandler processOutputHandler) throws ProcessException, IOException, InterruptedException {
// builder.addInputs(inputFile);
// super.runDexer(builder,dexOptions,processOutputHandler);
// 
// 
// }
@Override
public void convertByteCode(Collection<File> inputs, File outDexFolder, boolean multidex, final File mainDexList, DexOptions dexOptions, ProcessOutputHandler processOutputHandler, int minSdkVersion) throws IOException, InterruptedException, ProcessException {
    logger.warning("outDexFolder:" + outDexFolder.getAbsolutePath());
    FileUtils.forceMkdir(outDexFolder);
    // outDexFolder.mkdirs();
    AtlasDependencyTree atlasDependencyTree = AtlasBuildContext.androidDependencyTrees.get(variantContext.getVariantName());
    if (null != atlasDependencyTree) {
        ProcessOutputHandler outputHandler = new ParsingProcessOutputHandler(new ToolOutputParser(new DexParser(), Message.Kind.ERROR, LoggerWrapper.getLogger(DexByteCodeConverterHook.class)), new ToolOutputParser(new DexParser(), LoggerWrapper.getLogger(DexByteCodeConverterHook.class)), AtlasBuildContext.androidBuilderMap.get(variantContext.getProject()).getErrorReporter());
        for (final AwbBundle awbBundle : atlasDependencyTree.getAwbBundles()) {
            waitableExecutor.execute((Callable<Void>) () -> {
                try {
                    long start = System.currentTimeMillis();
                    // create dex
                    File dexOutputFile = ((AppVariantContext) variantContext).getAwbDexOutput(awbBundle.getName());
                    if (dexOutputFile.exists()) {
                        FileUtils.cleanDirectory(dexOutputFile);
                    } else {
                        FileUtils.forceMkdir(dexOutputFile);
                    }
                    // if some of our .jar input files exist, just reset the inputDir to null
                    AwbTransform awbTransform = variantOutputContext.getAwbTransformMap().get(awbBundle.getName());
                    List<File> inputFiles = new ArrayList<File>();
                    inputFiles.addAll(awbTransform.getInputFiles());
                    inputFiles.addAll(awbTransform.getInputLibraries());
                    if (null != awbTransform.getInputDirs()) {
                        inputFiles.addAll(awbTransform.getInputDirs());
                    }
                    if (variantContext.getScope().getDexer() == DexerTool.DX) {
                        AtlasBuildContext.androidBuilderMap.get(variantContext.getProject()).convertByteCode(inputFiles, dexOutputFile, false, null, dexOptions, outputHandler, true);
                    } else if (variantContext.getScope().getDexer() == DexerTool.D8) {
                        new AtlasD8Creator(inputFiles, ((AppVariantContext) variantContext).getAwbDexAchiveOutput(awbBundle), multidex, mainDexList, dexOptions, minSdkVersion, fileCache, processOutputHandler, variantContext, variantOutputContext).create(awbBundle);
                    }
                    if (awbBundle.isMBundle) {
                        mBundleSets.add(awbBundle);
                    }
                } catch (Exception e) {
                    throw new ProcessException(awbBundle.getName(), e);
                }
                return null;
            });
        }
    }
    File tempDexFolder = null;
    inputFile.addAll(AtlasBuildContext.atlasMainDexHelperMap.get(variantContext.getVariantName()).getAllMainDexJars());
    inputFile.addAll(AtlasBuildContext.atlasMainDexHelperMap.get(variantContext.getVariantName()).getInputDirs());
    logger.warning("maindex inputFile size :" + inputFile.size());
    if (variantContext.getScope().getDexer() == DexerTool.D8) {
        AtlasD8Creator atlasD8Creator = new AtlasD8Creator(inputs, ((AppVariantContext) variantContext).getMainDexAchive(), multidex, mainDexList, dexOptions, minSdkVersion, fileCache, processOutputHandler, variantContext, variantOutputContext);
        atlasD8Creator.setMainDexOut(outDexFolder);
        atlasD8Creator.create(new AwbBundle());
        return;
    }
    initDexExecutorService(dexOptions);
    if (!multidex) {
        if (fileCache != null && globalCacheBuilder == null) {
            globalCacheBuilder = new FileCache.Inputs.Builder(FileCache.Command.PREDEX_LIBRARY).putBoolean("multidex", false).putLong("minisdk", minSdkVersion).putString("dexoptions", dexOptions.getAdditionalParameters().toString()).putBoolean("jumbomode", dexOptions.getJumboMode()).putString("type", type);
            inputFile = new ArrayList<>(inputFile);
            Collections.sort((List<File>) inputFile);
            FileCache.Inputs inputsKey = globalCacheBuilder.putString("md5", MD5Util.getFileMd5(inputFile)).build();
            try {
                fileCache.createFile(outDexFolder, inputsKey, () -> {
                    logger.warning("dex inputFile missCache: " + inputFile.toString());
                    outDexFolder.mkdirs();
                    DexByteCodeConverterHook.super.convertByteCode(inputFile, outDexFolder, multidex, mainDexList, dexOptions, processOutputHandler, minSdkVersion);
                });
            } catch (ExecutionException e) {
                e.printStackTrace();
                failures.add(e);
            }
        } else {
            DexByteCodeConverterHook.super.convertByteCode(inputFile, outDexFolder, multidex, mainDexList, dexOptions, processOutputHandler, minSdkVersion);
        }
    // try {
    // for (Future future : futureList) {
    // future.get();
    // }
    // } catch (Exception e) {
    // throw new ProcessException(e);
    // }
    } else {
        if (mainDexList != null && !mainDexList.exists()) {
            generateMainDexList(mainDexList);
        }
        tempDexFolder = variantOutputContext.getMainDexOutDir();
        if (tempDexFolder.exists()) {
            FileUtils.cleanDirectory(tempDexFolder);
        }
        File finalTempDexFolder = tempDexFolder;
        if (fileCache != null && globalCacheBuilder == null) {
            if (mainDexList != null) {
                globalCacheBuilder = new FileCache.Inputs.Builder(FileCache.Command.PREDEX_LIBRARY).putBoolean("multidex", true).putFile("multidexlist", mainDexList, FileCache.FileProperties.HASH).putLong("minisdk", minSdkVersion).putString("dexoptions", dexOptions.getAdditionalParameters().toString()).putBoolean("jumbomode", dexOptions.getJumboMode()).putString("type", type);
            } else {
                globalCacheBuilder = new FileCache.Inputs.Builder(FileCache.Command.PREDEX_LIBRARY).putBoolean("multidex", true).putLong("minisdk", minSdkVersion).putString("dexoptions", dexOptions.getAdditionalParameters().toString()).putBoolean("jumbomode", dexOptions.getJumboMode()).putString("type", type);
            }
        }
        if (inputFile.size() == 1) {
            splitFile();
        }
        inputFile.parallelStream().forEach(file -> {
            File outPutFolder = new File(finalTempDexFolder, FilenameUtils.getBaseName(file.getName()));
            if (globalCacheBuilder != null && file.isFile()) {
                FileCache.Inputs.Builder builder = copyOf(globalCacheBuilder);
                FileCache.Inputs cacheInputs = null;
                if (file.isFile()) {
                    cacheInputs = builder.putFile("hash", file, FileCache.FileProperties.HASH).build();
                } else {
                    Collection<File> files = FileUtils.listFiles(file, new String[] { "class" }, true);
                    Collections.sort((List<File>) files);
                    cacheInputs = builder.putString("hash", MD5Util.getFileMd5(files)).build();
                }
                try {
                    fileCache.createFile(outPutFolder, cacheInputs, () -> {
                        logger.warning("maindex inputFile missCache:" + file.getAbsolutePath());
                        outPutFolder.mkdirs();
                        DexByteCodeConverterHook.super.convertByteCode(Arrays.asList(file), outPutFolder, true, mainDexList, dexOptions, processOutputHandler, minSdkVersion);
                    });
                } catch (Exception e) {
                    failures.add(e);
                    e.printStackTrace();
                }
            } else {
                logger.warning("maindex inputFile:" + file.getAbsolutePath());
                outPutFolder.mkdirs();
                try {
                    DexByteCodeConverterHook.super.convertByteCode(Arrays.asList(file), outPutFolder, true, mainDexList, dexOptions, processOutputHandler, minSdkVersion);
                } catch (Exception e) {
                    e.printStackTrace();
                    failures.add(e);
                }
            }
        });
        if (failures.size() > 0) {
            throw new ProcessException(failures.get(0));
        }
        // for (Future future : futureList) {
        // try {
        // future.get();
        // } catch (ExecutionException e) {
        // throw new ProcessException(e);
        // }
        // }
        // 
        // inputFile.stream().parallel().forEach(new Consumer<File>() {
        // @Override
        // public void accept(File file) {
        // fileCache.createFile()fileCacheMap.get(file)
        // }
        // });
        Collection<File> dexFiles = FileUtils.listFiles(tempDexFolder, new String[] { "dex" }, true);
        if (dexFiles != null) {
            logger.warning("maindex outDexFiles size:" + dexFiles.size());
            dexPaths = dexFiles.stream().map(file -> file.toPath()).collect(Collectors.toList());
        }
        mainforkJoinPool = new ForkJoinPool();
        atlasDexArchiveMerger = new AtlasDexArchiveMerger(mainforkJoinPool);
        if (!variantContext.getAtlasExtension().getTBuildConfig().getMergeBundlesDex()) {
            try {
                atlasDexArchiveMerger.mergeDexArchives(dexPaths, outDexFolder.toPath(), mainDexList == null ? null : mainDexList.toPath(), DexingType.LEGACY_MULTIDEX);
            } catch (DexArchiveMergerException e) {
                throw new ProcessException(e);
            }
        }
    }
    waitableExecutor.waitForTasksWithQuickFail(true);
    atomicInteger.set(FileUtils.listFiles(outDexFolder, new String[] { "dex" }, true).size());
    logger.warning("maindex final dexs size:" + atomicInteger.get());
    for (AwbBundle bundle : mBundleSets) {
        File awbDex = new File(((AppVariantContext) variantContext).getAwbDexOutput(bundle.getName()), "classes.dex");
        if (awbDex.exists() && !variantContext.getAtlasExtension().getTBuildConfig().getMergeBundlesDex()) {
            FileUtils.moveFile(awbDex, new File(outDexFolder, "classes" + atomicInteger.incrementAndGet() + ".dex"));
        } else if (awbDex.exists() && variantContext.getAtlasExtension().getTBuildConfig().getMergeBundlesDex()) {
            dexPaths.add(awbDex.toPath());
        } else {
            logger.warning(awbDex.getAbsoluteFile() + " is not exist!");
        }
    }
    if (variantContext.getAtlasExtension().getTBuildConfig().getMergeBundlesDex()) {
        try {
            atlasDexArchiveMerger.mergeDexArchives(dexPaths, outDexFolder.toPath(), null, DexingType.LEGACY_MULTIDEX);
        } catch (DexArchiveMergerException e) {
            e.printStackTrace();
        } finally {
        }
    }
    if (tempDexFolder != null && tempDexFolder.exists()) {
        FileUtils.deleteDirectory(tempDexFolder);
    }
}
Also used : ToolOutputParser(com.android.ide.common.blame.parser.ToolOutputParser) AwbBundle(com.taobao.android.builder.dependency.model.AwbBundle) ParsingProcessOutputHandler(com.android.ide.common.blame.ParsingProcessOutputHandler) ParsingProcessOutputHandler(com.android.ide.common.blame.ParsingProcessOutputHandler) AtlasDependencyTree(com.taobao.android.builder.dependency.AtlasDependencyTree) FileCacheException(com.taobao.android.builder.tools.cache.FileCacheException) FileCache(com.android.builder.utils.FileCache) DexParser(com.android.ide.common.blame.parser.DexParser) AwbTransform(com.android.build.gradle.internal.api.AwbTransform) JarFile(java.util.jar.JarFile) AppVariantContext(com.android.build.gradle.internal.api.AppVariantContext)

Aggregations

FileCache (com.android.builder.utils.FileCache)11 Nullable (com.android.annotations.Nullable)3 ProcessException (com.android.ide.common.process.ProcessException)3 File (java.io.File)3 JarFile (java.util.jar.JarFile)3 ParsingProcessOutputHandler (com.android.ide.common.blame.ParsingProcessOutputHandler)2 ToolOutputParser (com.android.ide.common.blame.parser.ToolOutputParser)2 LoggedProcessOutputHandler (com.android.ide.common.process.LoggedProcessOutputHandler)2 ProcessOutput (com.android.ide.common.process.ProcessOutput)2 AndroidLocation (com.android.prefs.AndroidLocation)2 IOException (java.io.IOException)2 SdkConstants (com.android.SdkConstants)1 NonNull (com.android.annotations.NonNull)1 com.android.build.api.transform (com.android.build.api.transform)1 QualifiedContent (com.android.build.api.transform.QualifiedContent)1 LoggerWrapper (com.android.build.gradle.internal.LoggerWrapper)1 AppVariantContext (com.android.build.gradle.internal.api.AppVariantContext)1 AppVariantOutputContext (com.android.build.gradle.internal.api.AppVariantOutputContext)1 AwbTransform (com.android.build.gradle.internal.api.AwbTransform)1 TransformManager (com.android.build.gradle.internal.pipeline.TransformManager)1