All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.build.gradle.tasks.StripDependenciesTask Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
/*
 * Copyright (C) 2015 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.tasks;

import com.android.annotations.NonNull;
import com.android.build.gradle.internal.LoggerWrapper;
import com.android.build.gradle.internal.NdkHandler;
import com.android.build.gradle.internal.core.Abi;
import com.android.build.gradle.internal.process.GradleProcessExecutor;
import com.android.build.gradle.ndk.internal.NdkNamingScheme;
import com.android.ide.common.process.LoggedProcessOutputHandler;
import com.android.ide.common.process.ProcessInfoBuilder;
import com.android.utils.FileUtils;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;

import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.incremental.IncrementalTaskInputs;
import org.gradle.api.tasks.incremental.InputFileDetails;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;

/**
 * Task to remove debug symbols from a native library depended on from jniLibs sourceSet.
 *
 * For files that already has the debug symbols stripped, simply copy the file.
 */
public class StripDependenciesTask extends DefaultTask {

    private Map stripExecutables = Maps.newHashMap();

    private Map inputFiles = Maps.newHashMap();

    @NonNull
    private Multimap stripedFiles = ArrayListMultimap.create();

    private File outputFolder;


    // ----- PUBLIC API -----

    /**
     * Strip command found in the NDK.
     */
    @SuppressWarnings("unused")  // Used for task input monitoring.
    @Input
    public Collection getStripExecutables() {
        return ImmutableList.copyOf(stripExecutables.values());
    }

    public void addStripExecutables(Map stripCommands) {
        this.stripExecutables.putAll(stripCommands);
    }

    @OutputDirectory
    public File getOutputFolder() {
        return outputFolder;
    }

    public void setOutputFolder(File outputFolder) {
        this.outputFolder = outputFolder;
    }

    @SuppressWarnings("unused") // Used by incremental task action.
    @InputFiles
    Iterable getInputFiles() {
        return Iterables.concat(stripedFiles.keySet(), inputFiles.keySet());
    }

    public void addInputFiles(Map files) {
        inputFiles.putAll(files);
    }

    public void addStripedFiles(Multimap files) {
        stripedFiles.putAll(files);
    }
    // ----- PRIVATE API -----

    @TaskAction
    void taskAction(IncrementalTaskInputs inputs) throws IOException {
        inputs.outOfDate(new Action() {
            @Override
            public void execute(InputFileDetails inputFileDetails) {
                File input = inputFileDetails.getFile();
                if (inputFiles.containsKey(input)) {
                    Abi abi = inputFiles.get(input);
                    File output = FileUtils.join(getOutputFolder(), abi.getName(), input.getName());
                    stripFile(input, output, abi);
                } else {
                    for (Abi abi : stripedFiles.get(input)) {
                        File output = FileUtils.join(
                                getOutputFolder(),
                                abi.getName(),
                                input.getName());
                        try {
                            FileUtils.mkdirs(output.getParentFile());
                            Files.copy(input, output);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        });
        inputs.removed(new Action() {
            @Override
            public void execute(InputFileDetails inputFileDetails) {
                File input = inputFileDetails.getFile();
                if (inputFiles.containsKey(input)) {
                    removeFile(input, inputFiles.get(input));
                } else {
                    for (Abi abi : stripedFiles.get(input)) {
                        removeFile(input, abi);
                    }
                }
            }
        });
    }

    private void removeFile(File file, Abi abi) {
        File output = FileUtils.join(getOutputFolder(), abi.getName(), file.getName());
        try {
            FileUtils.deleteIfExists(output);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void stripFile(File input, File output, Abi abi) {
        File outputDir = output.getParentFile();
        if (!output.getParentFile().exists()) {
            boolean result = outputDir.mkdirs();
            if (!result) {
                throw new RuntimeException("Unabled to create directory '"
                        + outputDir.toString() + "' for native binaries.");
            }
        }

        ProcessInfoBuilder builder = new ProcessInfoBuilder();
        builder.setExecutable(stripExecutables.get(abi));
        builder.addArgs("--strip-unneeded");
        builder.addArgs("-o");
        builder.addArgs(output.toString());
        builder.addArgs(input.toString());
        new GradleProcessExecutor(getProject()).execute(
                builder.createProcess(),
                new LoggedProcessOutputHandler(new LoggerWrapper(getLogger())));
    }


    // ----- ConfigAction -----

    public static class ConfigAction implements Action {
        @NonNull
        private final String buildType;
        @NonNull
        private final String flavor;
        @NonNull
        private final Map inputFiles;
        @NonNull
        private final Multimap stripedFiles;
        @NonNull
        private final File buildDir;
        @NonNull
        private final NdkHandler handler;

        public ConfigAction(
                @NonNull String buildType,
                @NonNull String flavor,
                @NonNull Map inputFiles,
                @NonNull Multimap stripedFiles,
                @NonNull File buildDir,
                @NonNull NdkHandler handler) {
            this.buildType = buildType;
            this.flavor = flavor;
            this.buildDir = buildDir;
            this.handler = handler;
            this.inputFiles = inputFiles;
            this.stripedFiles = stripedFiles;
        }

        @Override
        public void execute(@NonNull StripDependenciesTask task) {
            task.addInputFiles(inputFiles);
            task.addStripedFiles(stripedFiles);
            task.setOutputFolder(new File(
                    buildDir,
                    NdkNamingScheme.getOutputDirectoryName(buildType, flavor, "")));
            Map stripCommands = Maps.newHashMap();
            if (handler.isNdkDirConfigured()) {
                for(Abi abi : handler.getSupportedAbis()) {
                    stripCommands.put(abi, handler.getStripCommand(abi));
                    task.addStripExecutables(stripCommands);
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy