/* * Copyright 2016-present Facebook, Inc. * * 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.facebook.buck.go; import com.facebook.buck.cxx.CxxPlatform; import com.facebook.buck.cxx.DefaultCxxPlatforms; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.Flavor; import com.facebook.buck.model.FlavorDomain; import com.facebook.buck.util.MoreMaps; import com.facebook.buck.util.environment.Architecture; import com.facebook.buck.util.environment.Platform; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.util.Map; import java.util.Optional; public class GoPlatformFlavorDomain { // GOOS/GOARCH values from // https://github.com/golang/go/blob/master/src/go/build/syslist.go private static final ImmutableMap<String, Platform> GOOS_TO_PLATFORM_LIST = ImmutableMap.<String, Platform>builder() .put("linux", Platform.LINUX) .put("windows", Platform.WINDOWS) .put("darwin", Platform.MACOS) .put("android", Platform.UNKNOWN) .put("dragonfly", Platform.UNKNOWN) .put("freebsd", Platform.UNKNOWN) .put("nacl", Platform.UNKNOWN) .put("netbsd", Platform.UNKNOWN) .put("openbsd", Platform.UNKNOWN) .put("plan9", Platform.UNKNOWN) .put("solaris", Platform.UNKNOWN) .build(); private static final ImmutableMap<String, Architecture> GOARCH_TO_ARCH_LIST = ImmutableMap.<String, Architecture>builder() .put("386", Architecture.I386) .put("amd64", Architecture.X86_64) .put("amd64p32", Architecture.UNKNOWN) .put("arm", Architecture.ARM) .put("armbe", Architecture.ARMEB) .put("arm64", Architecture.AARCH64) .put("arm64be", Architecture.UNKNOWN) .put("ppc64", Architecture.PPC64) .put("ppc64le", Architecture.UNKNOWN) .put("mips", Architecture.MIPS) .put("mipsle", Architecture.MIPSEL) .put("mips64", Architecture.MIPS64) .put("mips64le", Architecture.MIPSEL64) .put("mips64p32", Architecture.UNKNOWN) .put("mips64p32le", Architecture.UNKNOWN) .put("ppc", Architecture.POWERPC) .put("s390", Architecture.UNKNOWN) .put("s390x", Architecture.UNKNOWN) .put("sparc", Architecture.UNKNOWN) .put("sparc64", Architecture.UNKNOWN) .build(); private final Platform currentPlatform; private final Architecture currentArchitecture; private FlavorDomain<CxxPlatform> cxxPlatforms; private ImmutableMap<String, Platform> goOsValues; private ImmutableMap<String, Architecture> goArchValues; public GoPlatformFlavorDomain( final Platform currentPlatform, final Architecture currentArchitecture, FlavorDomain<CxxPlatform> cxxPlatforms, Map<String, Platform> additionalOsValues, Map<String, Architecture> additionalArchValues) { this.currentPlatform = currentPlatform; this.currentArchitecture = currentArchitecture; this.cxxPlatforms = cxxPlatforms; this.goOsValues = MoreMaps.merge(GOOS_TO_PLATFORM_LIST, additionalOsValues); this.goArchValues = MoreMaps.merge(GOARCH_TO_ARCH_LIST, additionalArchValues); } public GoPlatformFlavorDomain( Platform currentPlatform, Architecture currentArchitecture, FlavorDomain<CxxPlatform> cxxPlatforms) { this(currentPlatform, currentArchitecture, cxxPlatforms, ImmutableMap.of(), ImmutableMap.of()); } public Optional<GoPlatform> getValue(Flavor flavor) { String[] components = flavor.getName().split("_"); if (components.length != 2) { return Optional.empty(); } Platform os = goOsValues.get(components[0]); Architecture arch = goArchValues.get(components[1]); if (os != null && arch != null) { return Optional.of( GoPlatform.builder() .setGoOs(components[0]) .setGoArch(components[1]) .setCxxPlatform(getCxxPlatform(os, arch)) .build()); } return Optional.empty(); } public Optional<GoPlatform> getValue(ImmutableSet<Flavor> flavors) { for (Flavor f : flavors) { Optional<GoPlatform> result = getValue(f); if (result.isPresent()) { return result; } } return Optional.empty(); } public Optional<GoPlatform> getValue(BuildTarget target) { return getValue(target.getFlavors()); } public boolean containsAnyOf(ImmutableSet<Flavor> flavors) { return getValue(flavors).isPresent(); } public Optional<GoPlatform> getValue(final Platform platform, final Architecture architecture) { Preconditions.checkArgument(platform != Platform.UNKNOWN); Preconditions.checkArgument(architecture != Architecture.UNKNOWN); Optional<Map.Entry<String, Platform>> osValue = goOsValues.entrySet().stream().filter(input -> input.getValue() == platform).findFirst(); Optional<Map.Entry<String, Architecture>> archValue = goArchValues .entrySet() .stream() .filter(input -> input.getValue() == architecture) .findFirst(); if (!osValue.isPresent() || !archValue.isPresent()) { return Optional.empty(); } return Optional.of( GoPlatform.builder() .setGoOs(osValue.get().getKey()) .setGoArch(archValue.get().getKey()) .setCxxPlatform(getCxxPlatform(platform, architecture)) .build()); } // TODO(mikekap): Move this somewhere closer to CxxPlatforms. private Optional<CxxPlatform> getCxxPlatform(Platform platform, Architecture arch) { if (platform == Platform.UNKNOWN || arch == Architecture.UNKNOWN) { return Optional.empty(); } if (platform == currentPlatform && arch == currentArchitecture) { return cxxPlatforms.getValue(ImmutableSet.of(DefaultCxxPlatforms.FLAVOR)); } return Optional.empty(); } }