blob: 6293890fcdb90c522233b52a340b01aa1553b322 [file] [log] [blame]
package com.google.devtools.build.lib.rules.cpp;
// Copyright 2018 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.
import com.google.auto.value.AutoValue;
import com.google.auto.value.AutoValue.CopyAnnotations;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.LibraryToLinkApi;
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.syntax.StarlarkList;
import java.util.List;
import javax.annotation.Nullable;
/**
* Encapsulates information for linking a library.
*
* <p>TODO(b/118663806): This class which shall be renamed later to LibraryToLink (once the old
* LibraryToLink implementation is removed) will have all the information necessary for linking a
* library in all of its variants : static params for executable, static params for dynamic library,
* dynamic params for executable and dynamic params for dynamic library.
*/
@AutoValue
@Immutable
@CopyAnnotations
public abstract class LibraryToLink implements LibraryToLinkApi<Artifact> {
public Artifact getDynamicLibraryForRuntimeOrNull(boolean linkingStatically) {
if (getDynamicLibrary() == null) {
return null;
}
if (linkingStatically && (getStaticLibrary() != null || getPicStaticLibrary() != null)) {
return null;
}
return getDynamicLibrary();
}
private LinkerInputs.LibraryToLink picStaticLibraryToLink;
private LinkerInputs.LibraryToLink staticLibraryToLink;
private LinkerInputs.LibraryToLink dynamicLibraryToLink;
private LinkerInputs.LibraryToLink interfaceLibraryToLink;
public abstract String getLibraryIdentifier();
@Nullable
@Override
public abstract Artifact getStaticLibrary();
@Nullable
public abstract ImmutableList<Artifact> getObjectFiles();
@Nullable
@Override
public Sequence<Artifact> getObjectFilesForStarlark() {
if (getObjectFiles() == null) {
return StarlarkList.empty();
}
return StarlarkList.immutableCopyOf(getObjectFiles());
}
@Nullable
public abstract ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends();
@Nullable
public abstract LtoCompilationContext getLtoCompilationContext();
@Nullable
@Override
public abstract Artifact getPicStaticLibrary();
@Nullable
public abstract ImmutableList<Artifact> getPicObjectFiles();
@Nullable
@Override
public Sequence<Artifact> getPicObjectFilesForStarlark() {
if (getPicObjectFiles() == null) {
return StarlarkList.empty();
}
return StarlarkList.immutableCopyOf(getPicObjectFiles());
}
@Nullable
public abstract ImmutableMap<Artifact, LtoBackendArtifacts> getPicSharedNonLtoBackends();
@Nullable
public abstract LtoCompilationContext getPicLtoCompilationContext();
@Nullable
@Override
public abstract Artifact getDynamicLibrary();
@Nullable
@Override
public abstract Artifact getResolvedSymlinkDynamicLibrary();
@Nullable
@Override
public abstract Artifact getInterfaceLibrary();
@Nullable
@Override
public abstract Artifact getResolvedSymlinkInterfaceLibrary();
@Override
public abstract boolean getAlwayslink();
// TODO(plf): This is just needed for Go, do not expose to Skylark and try to remove it. This was
// introduced to let a linker input declare that it needs debug info in the executable.
// Specifically, this was introduced for linking Go into a C++ binary when using the gccgo
// compiler.
abstract boolean getMustKeepDebug();
abstract boolean getDisableWholeArchive();
public static Builder builder() {
return new AutoValue_LibraryToLink.Builder()
.setMustKeepDebug(false)
.setAlwayslink(false)
.setDisableWholeArchive(false);
}
LinkerInputs.LibraryToLink getStaticLibraryToLink() {
Preconditions.checkNotNull(getStaticLibrary(), this);
if (staticLibraryToLink != null) {
return staticLibraryToLink;
}
staticLibraryToLink =
LinkerInputs.newInputLibrary(
getStaticLibrary(),
getAlwayslink()
? ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY
: ArtifactCategory.STATIC_LIBRARY,
getLibraryIdentifier(),
getObjectFiles(),
getLtoCompilationContext(),
getSharedNonLtoBackends(),
getMustKeepDebug(),
getDisableWholeArchive());
return staticLibraryToLink;
}
LinkerInputs.LibraryToLink getPicStaticLibraryToLink() {
Preconditions.checkNotNull(getPicStaticLibrary(), this);
if (picStaticLibraryToLink != null) {
return picStaticLibraryToLink;
}
picStaticLibraryToLink =
LinkerInputs.newInputLibrary(
getPicStaticLibrary(),
getAlwayslink()
? ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY
: ArtifactCategory.STATIC_LIBRARY,
getLibraryIdentifier(),
getPicObjectFiles(),
getPicLtoCompilationContext(),
getPicSharedNonLtoBackends(),
getMustKeepDebug(),
getDisableWholeArchive());
return picStaticLibraryToLink;
}
LinkerInputs.LibraryToLink getDynamicLibraryToLink() {
Preconditions.checkNotNull(getDynamicLibrary(), this);
if (dynamicLibraryToLink != null) {
return dynamicLibraryToLink;
}
if (getResolvedSymlinkDynamicLibrary() != null) {
dynamicLibraryToLink =
LinkerInputs.solibLibraryToLink(
getDynamicLibrary(), getResolvedSymlinkDynamicLibrary(), getLibraryIdentifier());
} else {
dynamicLibraryToLink =
LinkerInputs.newInputLibrary(
getDynamicLibrary(),
ArtifactCategory.DYNAMIC_LIBRARY,
getLibraryIdentifier(),
/* objectFiles */ ImmutableSet.of(),
LtoCompilationContext.EMPTY,
/* sharedNonLtoBackends */ ImmutableMap.of(),
getMustKeepDebug(),
getDisableWholeArchive());
}
return dynamicLibraryToLink;
}
LinkerInputs.LibraryToLink getInterfaceLibraryToLink() {
Preconditions.checkNotNull(getInterfaceLibrary());
if (interfaceLibraryToLink != null) {
return interfaceLibraryToLink;
}
if (getResolvedSymlinkInterfaceLibrary() != null) {
interfaceLibraryToLink =
LinkerInputs.solibLibraryToLink(
getInterfaceLibrary(), getResolvedSymlinkInterfaceLibrary(), getLibraryIdentifier());
} else {
interfaceLibraryToLink =
LinkerInputs.newInputLibrary(
getInterfaceLibrary(),
ArtifactCategory.INTERFACE_LIBRARY,
getLibraryIdentifier(),
/* objectFiles */ ImmutableSet.of(),
LtoCompilationContext.EMPTY,
/* sharedNonLtoBackends */ ImmutableMap.of(),
getMustKeepDebug(),
getDisableWholeArchive());
}
return interfaceLibraryToLink;
}
public static List<Artifact> getDynamicLibrariesForRuntime(
boolean linkingStatically, Iterable<LibraryToLink> libraries) {
ImmutableList.Builder<Artifact> dynamicLibrariesForRuntimeBuilder = ImmutableList.builder();
for (LibraryToLink libraryToLink : libraries) {
Artifact artifact = libraryToLink.getDynamicLibraryForRuntimeOrNull(linkingStatically);
if (artifact != null) {
dynamicLibrariesForRuntimeBuilder.add(artifact);
}
}
return dynamicLibrariesForRuntimeBuilder.build();
}
public static List<Artifact> getDynamicLibrariesForLinking(Iterable<LibraryToLink> libraries) {
ImmutableList.Builder<Artifact> dynamicLibrariesForLinkingBuilder = ImmutableList.builder();
for (LibraryToLink libraryToLink : libraries) {
if (libraryToLink.getInterfaceLibrary() != null) {
dynamicLibrariesForLinkingBuilder.add(libraryToLink.getInterfaceLibrary());
} else if (libraryToLink.getDynamicLibrary() != null) {
dynamicLibrariesForLinkingBuilder.add(libraryToLink.getDynamicLibrary());
}
}
return dynamicLibrariesForLinkingBuilder.build();
}
public abstract Builder toBuilder();
/** Builder for LibraryToLink. */
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setLibraryIdentifier(String libraryIdentifier);
public abstract Builder setStaticLibrary(Artifact staticLibrary);
public abstract Builder setObjectFiles(ImmutableList<Artifact> objectFiles);
abstract Builder setLtoCompilationContext(LtoCompilationContext ltoCompilationContext);
abstract Builder setSharedNonLtoBackends(
ImmutableMap<Artifact, LtoBackendArtifacts> sharedNonLtoBackends);
abstract Builder setPicStaticLibrary(Artifact picStaticLibrary);
abstract Builder setPicObjectFiles(ImmutableList<Artifact> picObjectFiles);
abstract Builder setPicLtoCompilationContext(LtoCompilationContext picLtoCompilationContext);
abstract Builder setPicSharedNonLtoBackends(
ImmutableMap<Artifact, LtoBackendArtifacts> picSharedNonLtoBackends);
public abstract Builder setDynamicLibrary(Artifact dynamicLibrary);
public abstract Builder setResolvedSymlinkDynamicLibrary(
Artifact resolvedSymlinkDynamicLibrary);
public abstract Builder setInterfaceLibrary(Artifact interfaceLibrary);
public abstract Builder setResolvedSymlinkInterfaceLibrary(
Artifact resolvedSymlinkInterfaceLibrary);
public abstract Builder setAlwayslink(boolean alwayslink);
public abstract Builder setMustKeepDebug(boolean mustKeepDebug);
public abstract Builder setDisableWholeArchive(boolean disableWholeArchive);
// Methods just for validation, not to be called externally.
abstract LibraryToLink autoBuild();
abstract String getLibraryIdentifier();
abstract Artifact getStaticLibrary();
abstract ImmutableList<Artifact> getObjectFiles();
abstract ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends();
abstract LtoCompilationContext getLtoCompilationContext();
abstract Artifact getPicStaticLibrary();
abstract ImmutableList<Artifact> getPicObjectFiles();
abstract ImmutableMap<Artifact, LtoBackendArtifacts> getPicSharedNonLtoBackends();
abstract LtoCompilationContext getPicLtoCompilationContext();
abstract Artifact getDynamicLibrary();
abstract Artifact getResolvedSymlinkDynamicLibrary();
abstract Artifact getInterfaceLibrary();
abstract Artifact getResolvedSymlinkInterfaceLibrary();
public LibraryToLink build() {
Preconditions.checkNotNull(getLibraryIdentifier());
Preconditions.checkState(
(getObjectFiles() == null
&& getLtoCompilationContext() == null
&& getSharedNonLtoBackends() == null)
|| getStaticLibrary() != null);
Preconditions.checkState(
(getPicObjectFiles() == null
&& getPicLtoCompilationContext() == null
&& getPicSharedNonLtoBackends() == null)
|| getPicStaticLibrary() != null);
Preconditions.checkState(
getResolvedSymlinkDynamicLibrary() == null || getDynamicLibrary() != null);
Preconditions.checkState(
getResolvedSymlinkInterfaceLibrary() == null
|| getResolvedSymlinkInterfaceLibrary() != null);
Preconditions.checkState(
getStaticLibrary() != null
|| getPicStaticLibrary() != null
|| getDynamicLibrary() != null
|| getInterfaceLibrary() != null);
return autoBuild();
}
}
}