// 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.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.util.Preconditions; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * A structured representation of the compilation outputs of a C++ rule. */ public class CcCompilationOutputs { /** * All .o files built by the target. */ private final ImmutableList<Artifact> objectFiles; /** * All .pic.o files built by the target. */ private final ImmutableList<Artifact> picObjectFiles; /** * Maps all .o bitcode files coming from a ThinLTO C(++) compilation under our control to the * corresponding minimized bitcode files that can be used for the LTO indexing step. */ private final ImmutableMap<Artifact, Artifact> ltoBitcodeFiles; /** * All .dwo files built by the target, corresponding to .o outputs. */ private final ImmutableList<Artifact> dwoFiles; /** * All .pic.dwo files built by the target, corresponding to .pic.o outputs. */ private final ImmutableList<Artifact> picDwoFiles; /** * All artifacts that are created if "--save_temps" is true. */ private final NestedSet<Artifact> temps; /** * All token .h.processed files created when preprocessing or parsing headers. */ private final ImmutableList<Artifact> headerTokenFiles; private final List<IncludeScannable> lipoScannables; private CcCompilationOutputs( ImmutableList<Artifact> objectFiles, ImmutableList<Artifact> picObjectFiles, ImmutableMap<Artifact, Artifact> ltoBitcodeFiles, ImmutableList<Artifact> dwoFiles, ImmutableList<Artifact> picDwoFiles, NestedSet<Artifact> temps, ImmutableList<Artifact> headerTokenFiles, ImmutableList<IncludeScannable> lipoScannables) { this.objectFiles = objectFiles; this.picObjectFiles = picObjectFiles; this.ltoBitcodeFiles = ltoBitcodeFiles; this.dwoFiles = dwoFiles; this.picDwoFiles = picDwoFiles; this.temps = temps; this.headerTokenFiles = headerTokenFiles; this.lipoScannables = lipoScannables; } /** * Returns whether this set of outputs has any object or .pic object files. */ public boolean isEmpty() { return picObjectFiles.isEmpty() && objectFiles.isEmpty(); } /** * Returns an unmodifiable view of the .o or .pic.o files set. * * @param usePic whether to return .pic.o files */ public ImmutableList<Artifact> getObjectFiles(boolean usePic) { return usePic ? picObjectFiles : objectFiles; } /** Returns unmodifiable map of bitcode object files resulting from compilation. */ public ImmutableMap<Artifact, Artifact> getLtoBitcodeFiles() { return ltoBitcodeFiles; } /** * Returns an unmodifiable view of the .dwo files set. */ public ImmutableList<Artifact> getDwoFiles() { return dwoFiles; } /** * Returns an unmodifiable view of the .pic.dwo files set. */ public ImmutableList<Artifact> getPicDwoFiles() { return picDwoFiles; } /** * Returns an unmodifiable view of the temp files set. */ public NestedSet<Artifact> getTemps() { return temps; } /** * Returns an unmodifiable view of the .h.processed files. */ public Iterable<Artifact> getHeaderTokenFiles() { return headerTokenFiles; } /** * Returns the {@link IncludeScannable} objects this C++ compile action contributes to a * LIPO context collector. */ public List<IncludeScannable> getLipoScannables() { return lipoScannables; } /** * Returns the output files that are considered "compiled" by this C++ compile action. */ NestedSet<Artifact> getFilesToCompile( boolean isLipoContextCollector, boolean parseHeaders, boolean usePic) { if (isLipoContextCollector) { return NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER); } NestedSetBuilder<Artifact> files = NestedSetBuilder.stableOrder(); files.addAll(getObjectFiles(usePic)); if (parseHeaders) { files.addAll(getHeaderTokenFiles()); } return files.build(); } public static final class Builder { private final Set<Artifact> objectFiles = new LinkedHashSet<>(); private final Set<Artifact> picObjectFiles = new LinkedHashSet<>(); private final ImmutableMap.Builder<Artifact, Artifact> ltoBitcodeFiles = ImmutableMap.builder(); private final Set<Artifact> dwoFiles = new LinkedHashSet<>(); private final Set<Artifact> picDwoFiles = new LinkedHashSet<>(); private final NestedSetBuilder<Artifact> temps = NestedSetBuilder.stableOrder(); private final Set<Artifact> headerTokenFiles = new LinkedHashSet<>(); private final List<IncludeScannable> lipoScannables = new ArrayList<>(); public CcCompilationOutputs build() { return new CcCompilationOutputs( ImmutableList.copyOf(objectFiles), ImmutableList.copyOf(picObjectFiles), ltoBitcodeFiles.build(), ImmutableList.copyOf(dwoFiles), ImmutableList.copyOf(picDwoFiles), temps.build(), ImmutableList.copyOf(headerTokenFiles), ImmutableList.copyOf(lipoScannables)); } public Builder merge(CcCompilationOutputs outputs) { this.objectFiles.addAll(outputs.objectFiles); this.picObjectFiles.addAll(outputs.picObjectFiles); this.dwoFiles.addAll(outputs.dwoFiles); this.picDwoFiles.addAll(outputs.picDwoFiles); this.temps.addTransitive(outputs.temps); this.headerTokenFiles.addAll(outputs.headerTokenFiles); this.lipoScannables.addAll(outputs.lipoScannables); return this; } /** * Adds an .o file. */ public Builder addObjectFile(Artifact artifact) { // We skip file extension checks for TreeArtifacts because they represent directory artifacts // without a file extension. Preconditions.checkArgument( artifact.isTreeArtifact() || Link.OBJECT_FILETYPES.matches(artifact.getFilename())); objectFiles.add(artifact); return this; } public Builder addObjectFiles(Iterable<Artifact> artifacts) { for (Artifact artifact : artifacts) { Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(artifact.getFilename())); } Iterables.addAll(objectFiles, artifacts); return this; } /** * Adds a .pic.o file. */ public Builder addPicObjectFile(Artifact artifact) { picObjectFiles.add(artifact); return this; } public Builder addLTOBitcodeFile(Artifact fullBitcode, Artifact ltoIndexingBitcode) { ltoBitcodeFiles.put(fullBitcode, ltoIndexingBitcode); return this; } public Builder addLTOBitcodeFile(ImmutableMap<Artifact, Artifact> artifacts) { ltoBitcodeFiles.putAll(artifacts); return this; } public Builder addPicObjectFiles(Iterable<Artifact> artifacts) { for (Artifact artifact : artifacts) { Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(artifact.getFilename())); } Iterables.addAll(picObjectFiles, artifacts); return this; } public Builder addDwoFile(Artifact artifact) { dwoFiles.add(artifact); return this; } public Builder addPicDwoFile(Artifact artifact) { picDwoFiles.add(artifact); return this; } /** * Adds temp files. */ public Builder addTemps(Iterable<Artifact> artifacts) { temps.addAll(artifacts); return this; } public Builder addHeaderTokenFile(Artifact artifact) { headerTokenFiles.add(artifact); return this; } /** * Adds an {@link IncludeScannable} that this compilation output object contributes to a * LIPO context collector. */ public Builder addLipoScannable(IncludeScannable scannable) { lipoScannables.add(scannable); return this; } } }