com.github.blindpirate.gogradle.task.go.GoBuild.java Source code

Java tutorial

Introduction

Here is the source code for com.github.blindpirate.gogradle.task.go.GoBuild.java

Source

/*
 * Copyright 2016-2017 the original author or authors.
 *
 * 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.github.blindpirate.gogradle.task.go;

import com.github.blindpirate.gogradle.Go;
import com.github.blindpirate.gogradle.GolangPluginSetting;
import com.github.blindpirate.gogradle.common.GoSourceCodeFilter;
import com.github.blindpirate.gogradle.crossplatform.Arch;
import com.github.blindpirate.gogradle.crossplatform.GoBinaryManager;
import com.github.blindpirate.gogradle.crossplatform.Os;
import com.github.blindpirate.gogradle.util.Assert;
import com.github.blindpirate.gogradle.util.MapUtils;
import com.github.blindpirate.gogradle.util.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import javax.inject.Inject;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import static com.github.blindpirate.gogradle.common.GoSourceCodeFilter.SourceSetType.PROJECT_AND_VENDOR_BUILD_FILES;
import static com.github.blindpirate.gogradle.task.GolangTaskContainer.INSTALL_DEPENDENCIES_TASK_NAME;
import static com.github.blindpirate.gogradle.task.GolangTaskContainer.RESOLVE_BUILD_DEPENDENCIES_TASK_NAME;
import static com.github.blindpirate.gogradle.util.StringUtils.capitalizeFirstLetter;
import static com.github.blindpirate.gogradle.util.StringUtils.splitAndTrim;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;

public class GoBuild extends Go {
    @Inject
    private GolangPluginSetting setting;
    @Inject
    private GoBinaryManager binaryManager;

    private static final Pattern TARGET_PLATFORMS_PATTERN = Pattern
            .compile("(\\s*\\w+-\\w+\\s*)(,\\s*\\w+-\\w+\\s*)*");
    private static final Pattern TARGET_PLATFORM_PATTERN = Pattern.compile("\\w+-\\w+");
    private static final String DEFAULT_OUTPUT_LOCATION = "./.gogradle/${PROJECT_NAME}-${GOOS}-${GOARCH}";

    private String outputLocation;

    private List<Pair<Os, Arch>> targetPlatforms = singletonList(Pair.of(Os.getHostOs(), Arch.getHostArch()));

    public GoBuild() {
        setDescription("Run build and generate output.");
    }

    public void setOutputLocation(String outputLocation) {
        this.outputLocation = outputLocation;
    }

    @Override
    public void afterEvaluate() {
        targetPlatforms.forEach(osArchPair -> {
            Os os = osArchPair.getLeft();
            Arch arch = osArchPair.getRight();

            Go task = createSingleGoTask(os, arch);
            task.dependsOn(INSTALL_DEPENDENCIES_TASK_NAME, RESOLVE_BUILD_DEPENDENCIES_TASK_NAME);
            configureSubTask(task, os, arch);
        });

        if (!this.goActions.isEmpty()) {
            this.goActions.clear();
        }
    }

    private boolean noCustomActions() {
        return goActions.isEmpty();
    }

    private void configureSubTask(Go subTask, Os os, Arch arch) {
        configureStdoutStderr(subTask);
        subTask.setContinueOnFailure(continueOnFailure);
        configureActions(subTask);
        configureEnvironment(os, arch, subTask);
        configureInputsOutputs(subTask, os, arch);
        this.dependsOn(subTask);
    }

    private void configureInputsOutputs(Go subTask, Os os, Arch arch) {
        if (noCustomActions() || outputLocation != null) {
            subTask.getInputs().files((Callable<Collection<File>>) () -> GoSourceCodeFilter
                    .filterGoFiles(getProjectDir(), PROJECT_AND_VENDOR_BUILD_FILES));

            subTask.getOutputs().file(new File(getProjectDir(), getRenderedOutputLocation(os, arch)));

            Map<String, Object> inputProperties = new HashMap<>();
            inputProperties.put("buildTags", (Callable<List<String>>) () -> setting.getBuildTags());
            inputProperties.put("goVersion", (Callable<String>) () -> binaryManager.getGoVersion());
            inputProperties.put("environment", getEffectiveEnvironment(os, arch));
            subTask.getInputs().properties(inputProperties);
        }
    }

    private String getRenderedOutputLocation(Os os, Arch arch) {
        Map<String, Object> context = new HashMap<>(getEffectiveEnvironment(os, arch));
        context.put("PROJECT_NAME", getProject().getName());
        context.put("PROJECT_VERSION", getProject().getVersion());
        return StringUtils.render(getOutputLocation(), context);
    }

    public String getOutputLocation() {
        return outputLocation == null ? DEFAULT_OUTPUT_LOCATION : outputLocation;
    }

    private void configureStdoutStderr(Go subTask) {
        subTask.stdout(this.stdoutLineConsumer);
        subTask.stderr(this.stderrLineConsumer);
    }

    private void configureActions(Go subTask) {
        if (noCustomActions()) {
            subTask.go(Arrays.asList("build", "-o", getOutputLocation(), setting.getPackagePath()));
        } else {
            goActions.forEach(subTask::addGoAction);
        }
    }

    private void configureEnvironment(Os os, Arch arch, Go task) {
        Map<String, String> env = getEffectiveEnvironment(os, arch);
        env.putAll(this.environment);
        task.environment(env);
    }

    private Go createSingleGoTask(Os os, Arch arch) {
        String taskName = "build" + capitalizeFirstLetter(os.toString()) + capitalizeFirstLetter(arch.toString());
        return getProject().getTasks().create(taskName, Go.class);
    }

    @Deprecated
    public void setTargetPlatform(String targetPlatform) {
        Matcher matcher = TARGET_PLATFORMS_PATTERN.matcher(targetPlatform);
        Assert.isTrue(matcher.matches(), "Illegal target platform:" + targetPlatform);
        targetPlatforms = extractPlatforms(targetPlatform);
        removeDuplicates();
    }

    public void setTargetPlatform(List<String> targetPlatformList) {
        Assert.isNotEmpty(targetPlatformList, "Target platform cannot be empty!");
        Assert.isTrue(targetPlatformList.stream().allMatch(s -> TARGET_PLATFORM_PATTERN.matcher(s).matches()),
                "Illegal target platform:" + targetPlatformList);
        targetPlatforms = targetPlatformList.stream().map(this::extractOne).collect(toList());
        removeDuplicates();
    }

    private void removeDuplicates() {
        targetPlatforms = new ArrayList<>(new LinkedHashSet<>(targetPlatforms));
    }

    private List<Pair<Os, Arch>> extractPlatforms(String targetPlatform) {
        String[] platforms = splitAndTrim(targetPlatform, ",");
        return Stream.of(platforms).map(this::extractOne).collect(toList());
    }

    private Pair<Os, Arch> extractOne(String osAndArch) {
        String[] osArch = splitAndTrim(osAndArch, "\\-");
        Os os = Os.of(osArch[0]);
        Arch arch = Arch.of(osArch[1]);
        return Pair.of(os, arch);
    }

    private Map<String, String> getEffectiveEnvironment(Os os, Arch arch) {
        Map<String, String> result = MapUtils.asMap("GOOS", os.toString(), "GOARCH", arch.toString(), "GOEXE",
                os.exeExtension());
        result.putAll(environment);
        return result;
    }
}