| // Copyright 2014 The Bazel Authors. All rights reserved. |
| // |
| // 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.google.devtools.build.lib.rules.cpp; |
| |
| import com.google.common.base.Objects; |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; |
| import com.google.devtools.build.lib.events.Location; |
| import com.google.devtools.build.lib.packages.NativeInfo; |
| import com.google.devtools.build.lib.packages.NativeProvider; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; |
| import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcLinkingInfoApi; |
| import com.google.devtools.build.lib.syntax.Environment; |
| import com.google.devtools.build.lib.syntax.EvalException; |
| import com.google.devtools.build.lib.syntax.FunctionSignature; |
| import com.google.devtools.build.lib.syntax.Runtime; |
| import com.google.devtools.build.lib.syntax.SkylarkType; |
| import java.util.Collection; |
| import javax.annotation.Nullable; |
| |
| /** Wrapper for every C++ linking provider. */ |
| @Immutable |
| @AutoCodec |
| public final class CcLinkingInfo extends NativeInfo implements CcLinkingInfoApi { |
| |
| private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE = |
| FunctionSignature.WithValues.create( |
| FunctionSignature.of( |
| /* numMandatoryPositionals= */ 0, |
| /* numOptionalPositionals= */ 0, |
| // TODO(plf): Make CcLinkParams parameters mandatory once existing rules have been |
| // migrated. |
| /* numMandatoryNamedOnly= */ 0, |
| /* starArg= */ false, |
| /* kwArg= */ false, |
| "static_mode_params_for_dynamic_library", |
| "static_mode_params_for_executable", |
| "dynamic_mode_params_for_dynamic_library", |
| "dynamic_mode_params_for_executable"), |
| /* defaultValues= */ ImmutableList.of( |
| Runtime.NONE, Runtime.NONE, Runtime.NONE, Runtime.NONE), |
| /* types= */ ImmutableList.of( |
| SkylarkType.of(CcLinkParams.class), |
| SkylarkType.of(CcLinkParams.class), |
| SkylarkType.of(CcLinkParams.class), |
| SkylarkType.of(CcLinkParams.class))); |
| |
| @Nullable |
| private static Object nullIfNone(Object object) { |
| return nullIfNone(object, Object.class); |
| } |
| |
| @Nullable |
| private static <T> T nullIfNone(Object object, Class<T> type) { |
| return object != Runtime.NONE ? type.cast(object) : null; |
| } |
| |
| public static final NativeProvider<CcLinkingInfo> PROVIDER = |
| new NativeProvider<CcLinkingInfo>(CcLinkingInfo.class, "CcLinkingInfo", SIGNATURE) { |
| @Override |
| @SuppressWarnings("unchecked") |
| protected CcLinkingInfo createInstanceFromSkylark( |
| Object[] args, Environment env, Location loc) throws EvalException { |
| CcCommon.checkLocationWhitelisted( |
| env.getSemantics(), |
| loc, |
| env.getGlobals().getTransitiveLabel().getPackageIdentifier().toString()); |
| int i = 0; |
| CcLinkParams staticModeParamsForDynamicLibrary = (CcLinkParams) nullIfNone(args[i++]); |
| CcLinkParams staticModeParamsForExecutable = (CcLinkParams) nullIfNone(args[i++]); |
| CcLinkParams dynamicModeParamsForDynamicLibrary = (CcLinkParams) nullIfNone(args[i++]); |
| CcLinkParams dynamicModeParamsForExecutable = (CcLinkParams) nullIfNone(args[i++]); |
| CcLinkingInfo.Builder ccLinkingInfoBuilder = CcLinkingInfo.Builder.create(); |
| if (staticModeParamsForDynamicLibrary == null |
| || staticModeParamsForExecutable == null |
| || dynamicModeParamsForDynamicLibrary == null |
| || dynamicModeParamsForExecutable == null) { |
| throw new EvalException( |
| loc, "Every CcLinkParams parameter must be passed to CcLinkingInfo."); |
| } |
| ccLinkingInfoBuilder |
| .setStaticModeParamsForDynamicLibrary(staticModeParamsForDynamicLibrary) |
| .setStaticModeParamsForExecutable(staticModeParamsForExecutable) |
| .setDynamicModeParamsForDynamicLibrary(dynamicModeParamsForDynamicLibrary) |
| .setDynamicModeParamsForExecutable(dynamicModeParamsForExecutable); |
| return ccLinkingInfoBuilder.build(); |
| } |
| }; |
| |
| public static final CcLinkingInfo EMPTY = |
| CcLinkingInfo.Builder.create() |
| .setStaticModeParamsForDynamicLibrary(CcLinkParams.EMPTY) |
| .setStaticModeParamsForExecutable(CcLinkParams.EMPTY) |
| .setDynamicModeParamsForDynamicLibrary(CcLinkParams.EMPTY) |
| .setDynamicModeParamsForExecutable(CcLinkParams.EMPTY) |
| .build(); |
| |
| private final CcLinkParams staticModeParamsForExecutable; |
| private final CcLinkParams staticModeParamsForDynamicLibrary; |
| private final CcLinkParams dynamicModeParamsForExecutable; |
| private final CcLinkParams dynamicModeParamsForDynamicLibrary; |
| |
| @AutoCodec.Instantiator |
| @VisibleForSerialization |
| CcLinkingInfo( |
| CcLinkParams staticModeParamsForExecutable, |
| CcLinkParams staticModeParamsForDynamicLibrary, |
| CcLinkParams dynamicModeParamsForExecutable, |
| CcLinkParams dynamicModeParamsForDynamicLibrary) { |
| super(PROVIDER); |
| this.staticModeParamsForExecutable = staticModeParamsForExecutable; |
| this.staticModeParamsForDynamicLibrary = staticModeParamsForDynamicLibrary; |
| this.dynamicModeParamsForExecutable = dynamicModeParamsForExecutable; |
| this.dynamicModeParamsForDynamicLibrary = dynamicModeParamsForDynamicLibrary; |
| } |
| |
| @Override |
| public CcLinkParams getStaticModeParamsForExecutable() { |
| return staticModeParamsForExecutable; |
| } |
| |
| @Override |
| public CcLinkParams getStaticModeParamsForDynamicLibrary() { |
| return staticModeParamsForDynamicLibrary; |
| } |
| |
| @Override |
| public CcLinkParams getDynamicModeParamsForExecutable() { |
| return dynamicModeParamsForExecutable; |
| } |
| |
| @Override |
| public CcLinkParams getDynamicModeParamsForDynamicLibrary() { |
| return dynamicModeParamsForDynamicLibrary; |
| } |
| |
| public static CcLinkingInfo merge(Collection<CcLinkingInfo> ccLinkingInfos) { |
| CcLinkParams.Builder staticModeParamsForDynamicLibraryBuilder = CcLinkParams.builder(); |
| CcLinkParams.Builder staticModeParamsForExecutableBuilder = CcLinkParams.builder(); |
| CcLinkParams.Builder dynamicModeParamsForDynamicLibraryBuilder = CcLinkParams.builder(); |
| CcLinkParams.Builder dynamicModeParamsForExecutableBuilder = CcLinkParams.builder(); |
| for (CcLinkingInfo ccLinkingInfo : ccLinkingInfos) { |
| staticModeParamsForDynamicLibraryBuilder.addTransitiveArgs( |
| ccLinkingInfo.getStaticModeParamsForDynamicLibrary()); |
| staticModeParamsForExecutableBuilder.addTransitiveArgs( |
| ccLinkingInfo.getStaticModeParamsForExecutable()); |
| dynamicModeParamsForDynamicLibraryBuilder.addTransitiveArgs( |
| ccLinkingInfo.getDynamicModeParamsForDynamicLibrary()); |
| dynamicModeParamsForExecutableBuilder.addTransitiveArgs( |
| ccLinkingInfo.getDynamicModeParamsForExecutable()); |
| } |
| return new CcLinkingInfo.Builder() |
| .setStaticModeParamsForDynamicLibrary(staticModeParamsForDynamicLibraryBuilder.build()) |
| .setStaticModeParamsForExecutable(staticModeParamsForExecutableBuilder.build()) |
| .setDynamicModeParamsForDynamicLibrary(dynamicModeParamsForDynamicLibraryBuilder.build()) |
| .setDynamicModeParamsForExecutable(dynamicModeParamsForExecutableBuilder.build()) |
| .build(); |
| } |
| |
| public CcLinkParams getCcLinkParams(boolean staticMode, boolean forDynamicLibrary) { |
| if (staticMode) { |
| if (forDynamicLibrary) { |
| return getStaticModeParamsForDynamicLibrary(); |
| } else { |
| return getStaticModeParamsForExecutable(); |
| } |
| } else { |
| if (forDynamicLibrary) { |
| return getDynamicModeParamsForDynamicLibrary(); |
| } else { |
| return getDynamicModeParamsForExecutable(); |
| } |
| } |
| } |
| |
| /** A Builder for {@link CcLinkingInfo}. */ |
| public static class Builder { |
| CcLinkParams staticModeParamsForDynamicLibrary; |
| CcLinkParams staticModeParamsForExecutable; |
| CcLinkParams dynamicModeParamsForDynamicLibrary; |
| CcLinkParams dynamicModeParamsForExecutable; |
| |
| public static CcLinkingInfo.Builder create() { |
| return new CcLinkingInfo.Builder(); |
| } |
| |
| public Builder setStaticModeParamsForDynamicLibrary(CcLinkParams ccLinkParams) { |
| Preconditions.checkState(this.staticModeParamsForDynamicLibrary == null); |
| this.staticModeParamsForDynamicLibrary = ccLinkParams; |
| return this; |
| } |
| |
| public Builder setStaticModeParamsForExecutable(CcLinkParams ccLinkParams) { |
| Preconditions.checkState(this.staticModeParamsForExecutable == null); |
| this.staticModeParamsForExecutable = ccLinkParams; |
| return this; |
| } |
| |
| public Builder setDynamicModeParamsForDynamicLibrary(CcLinkParams ccLinkParams) { |
| Preconditions.checkState(this.dynamicModeParamsForDynamicLibrary == null); |
| this.dynamicModeParamsForDynamicLibrary = ccLinkParams; |
| return this; |
| } |
| |
| public Builder setDynamicModeParamsForExecutable(CcLinkParams ccLinkParams) { |
| Preconditions.checkState(this.dynamicModeParamsForExecutable == null); |
| this.dynamicModeParamsForExecutable = ccLinkParams; |
| return this; |
| } |
| |
| public CcLinkingInfo build() { |
| Preconditions.checkNotNull(staticModeParamsForExecutable); |
| Preconditions.checkNotNull(staticModeParamsForDynamicLibrary); |
| Preconditions.checkNotNull(dynamicModeParamsForExecutable); |
| Preconditions.checkNotNull(dynamicModeParamsForDynamicLibrary); |
| return new CcLinkingInfo( |
| staticModeParamsForExecutable, |
| staticModeParamsForDynamicLibrary, |
| dynamicModeParamsForExecutable, |
| dynamicModeParamsForDynamicLibrary); |
| } |
| } |
| |
| @Override |
| public boolean equals(Object otherObject) { |
| if (!(otherObject instanceof CcLinkingInfo)) { |
| return false; |
| } |
| CcLinkingInfo other = (CcLinkingInfo) otherObject; |
| if (this == other) { |
| return true; |
| } |
| if (!this.staticModeParamsForExecutable.equals(other.staticModeParamsForExecutable) |
| || !this.staticModeParamsForDynamicLibrary.equals(other.staticModeParamsForDynamicLibrary) |
| || !this.dynamicModeParamsForExecutable.equals(other.dynamicModeParamsForExecutable) |
| || !this.dynamicModeParamsForDynamicLibrary.equals( |
| other.dynamicModeParamsForDynamicLibrary)) { |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hashCode( |
| staticModeParamsForExecutable, |
| staticModeParamsForDynamicLibrary, |
| dynamicModeParamsForExecutable, |
| dynamicModeParamsForDynamicLibrary); |
| } |
| } |