use of com.google.devtools.build.lib.vfs.PathFragment in project bazel by bazelbuild.
the class NativeDepsHelper method linkAndroidNativeDepsIfPresent.
/**
* Creates an Action to create a dynamic library for Android by linking all native code (C/C++)
* libraries in the transitive dependency closure of a rule.
*
* <p>We link the native deps in the equivalent of linkstatic=1, linkshared=1 mode.
*
* <p>linkstatic=1 means mostly-static mode, i.e. we select the ".a" (or ".pic.a") files, but we
* don't include "-static" in linkopts.
*
* <p>linkshared=1 means we prefer the ".pic.a" files to the ".a" files, and the LinkTargetType is
* set to DYNAMIC_LIBRARY which causes Link.java to include "-shared" in the linker options.
*
* <p>It is possible that this function may have no work to do if there are no native libraries
* in the transitive closure, or if the only native libraries in the transitive closure are
* already shared libraries. In this case, this function returns {@code null}.
*
* @param ruleContext the rule context to determine the native deps library
* @param linkParams the {@link CcLinkParams} for the rule, collected with linkstatic = 1 and
* linkshared = 1
* @return the native deps library, or null if there was no code which needed to be linked in the
* transitive closure.
*/
public static Artifact linkAndroidNativeDepsIfPresent(final RuleContext ruleContext, CcLinkParams linkParams, final BuildConfiguration configuration, CcToolchainProvider toolchain) throws InterruptedException {
if (!containsCodeToLink(linkParams.getLibraries())) {
return null;
}
PathFragment labelName = new PathFragment(ruleContext.getLabel().getName());
String libraryIdentifier = ruleContext.getUniqueDirectory(ANDROID_UNIQUE_DIR).getRelative(labelName.replaceName("lib" + labelName.getBaseName())).getPathString();
Artifact nativeDeps = ruleContext.getUniqueDirectoryArtifact(ANDROID_UNIQUE_DIR, labelName.replaceName("lib" + labelName.getBaseName() + ".so"), configuration.getBinDirectory(ruleContext.getRule().getRepository()));
return createNativeDepsAction(ruleContext, linkParams, /** extraLinkOpts */
ImmutableList.<String>of(), configuration, toolchain, nativeDeps, libraryIdentifier, configuration.getBinDirectory(ruleContext.getRule().getRepository()), /*useDynamicRuntime*/
false).getLibrary();
}
use of com.google.devtools.build.lib.vfs.PathFragment in project bazel by bazelbuild.
the class NativeDepsHelper method createNativeDepsAction.
public static NativeDepsRunfiles createNativeDepsAction(final RuleContext ruleContext, CcLinkParams linkParams, Collection<String> extraLinkOpts, BuildConfiguration configuration, CcToolchainProvider toolchain, Artifact nativeDeps, String libraryIdentifier, Root bindirIfShared, boolean useDynamicRuntime) throws InterruptedException {
Preconditions.checkState(ruleContext.isLegalFragment(CppConfiguration.class), "%s does not have access to CppConfiguration", ruleContext.getRule().getRuleClass());
List<String> linkopts = new ArrayList<>(extraLinkOpts);
linkopts.addAll(linkParams.flattenedLinkopts());
Map<Artifact, NestedSet<Artifact>> linkstamps = CppHelper.resolveLinkstamps(ruleContext, linkParams);
List<Artifact> buildInfoArtifacts = linkstamps.isEmpty() ? ImmutableList.<Artifact>of() : ruleContext.getAnalysisEnvironment().getBuildInfo(ruleContext, CppBuildInfo.KEY, configuration);
boolean shareNativeDeps = configuration.getFragment(CppConfiguration.class).shareNativeDeps();
NestedSet<LibraryToLink> linkerInputs = linkParams.getLibraries();
Artifact sharedLibrary;
if (shareNativeDeps) {
PathFragment sharedPath = getSharedNativeDepsPath(LinkerInputs.toLibraryArtifacts(linkerInputs), linkopts, linkstamps.keySet(), buildInfoArtifacts, ruleContext.getFeatures());
libraryIdentifier = sharedPath.getPathString();
sharedLibrary = ruleContext.getShareableArtifact(sharedPath.replaceName(sharedPath.getBaseName() + ".so"), configuration.getBinDirectory(ruleContext.getRule().getRepository()));
} else {
sharedLibrary = nativeDeps;
}
FdoSupportProvider fdoSupport = CppHelper.getFdoSupport(ruleContext, ":cc_toolchain");
CppLinkActionBuilder builder = new CppLinkActionBuilder(ruleContext, sharedLibrary, configuration, toolchain, fdoSupport);
if (useDynamicRuntime) {
builder.setRuntimeInputs(ArtifactCategory.DYNAMIC_LIBRARY, toolchain.getDynamicRuntimeLinkMiddleman(), toolchain.getDynamicRuntimeLinkInputs());
} else {
builder.setRuntimeInputs(ArtifactCategory.STATIC_LIBRARY, toolchain.getStaticRuntimeLinkMiddleman(), toolchain.getStaticRuntimeLinkInputs());
}
CppLinkAction linkAction = builder.setLinkArtifactFactory(SHAREABLE_LINK_ARTIFACT_FACTORY).setCrosstoolInputs(toolchain.getLink()).addLibraries(linkerInputs).setLinkType(LinkTargetType.DYNAMIC_LIBRARY).setLinkStaticness(LinkStaticness.MOSTLY_STATIC).setLibraryIdentifier(libraryIdentifier).addLinkopts(linkopts).setNativeDeps(true).addLinkstamps(linkstamps).build();
ruleContext.registerAction(linkAction);
Artifact linkerOutput = linkAction.getPrimaryOutput();
if (shareNativeDeps) {
// Collect dynamic-linker-resolvable symlinks for C++ runtime library dependencies.
// Note we only need these symlinks when --share_native_deps is on, as shared native deps
// mangle path names such that the library's conventional _solib RPATH entry
// no longer resolves (because the target directory's relative depth gets lost).
List<Artifact> runtimeSymlinks;
if (useDynamicRuntime) {
runtimeSymlinks = new LinkedList<>();
for (final Artifact runtimeInput : toolchain.getDynamicRuntimeLinkInputs()) {
final Artifact runtimeSymlink = ruleContext.getPackageRelativeArtifact(getRuntimeLibraryPath(ruleContext, runtimeInput), bindirIfShared);
// Since runtime library symlinks are underneath the target's output directory and
// multiple targets may share the same output directory, we need to make sure this
// symlink's generating action is only set once.
ruleContext.registerAction(new SymlinkAction(ruleContext.getActionOwner(), runtimeInput, runtimeSymlink, null));
runtimeSymlinks.add(runtimeSymlink);
}
} else {
runtimeSymlinks = ImmutableList.of();
}
ruleContext.registerAction(new SymlinkAction(ruleContext.getActionOwner(), linkerOutput, nativeDeps, null));
return new NativeDepsRunfiles(nativeDeps, runtimeSymlinks);
}
return new NativeDepsRunfiles(linkerOutput, ImmutableList.<Artifact>of());
}
use of com.google.devtools.build.lib.vfs.PathFragment in project bazel by bazelbuild.
the class FdoSupport method readAutoFdoImports.
/**
* Reads a .afdo.imports file and stores the imports information.
*/
private static ImmutableMultimap<PathFragment, PathFragment> readAutoFdoImports(Path importsFile) throws IOException, FdoException {
ImmutableMultimap.Builder<PathFragment, PathFragment> importBuilder = ImmutableMultimap.builder();
for (String line : FileSystemUtils.iterateLinesAsLatin1(importsFile)) {
line = line.trim();
if (line.isEmpty()) {
continue;
}
int colonIndex = line.indexOf(':');
if (colonIndex < 0) {
continue;
}
PathFragment key = new PathFragment(line.substring(0, colonIndex));
if (key.isAbsolute()) {
throw new FdoException("Absolute paths not allowed in afdo imports file " + importsFile + ": " + key);
}
for (String auxFile : line.substring(colonIndex + 1).split(" ")) {
if (auxFile.length() == 0) {
continue;
}
importBuilder.put(key, new PathFragment(auxFile));
}
}
return importBuilder.build();
}
use of com.google.devtools.build.lib.vfs.PathFragment in project bazel by bazelbuild.
the class FdoSupport method getGcdaArtifactsForObjectFileName.
/**
* Returns a list of .gcda file artifacts for an object file path.
*
* <p>The resulting set is either empty (because no .gcda file exists for the
* given object file) or contains one or two artifacts (the file itself and a
* symlink to it).
*/
private ImmutableList<Artifact> getGcdaArtifactsForObjectFileName(RuleContext ruleContext, FdoSupportProvider fdoSupportProvider, PathFragment objectFileName, Label lipoLabel) {
// We put the .gcda files relative to the location of the .o file in the instrumentation run.
String gcdaExt = Iterables.getOnlyElement(CppFileTypes.COVERAGE_DATA.getExtensions());
PathFragment baseName = FileSystemUtils.replaceExtension(objectFileName, gcdaExt);
PathFragment gcdaFile = getNonLipoObjDir(ruleContext, lipoLabel).getRelative(baseName);
if (!gcdaFiles.contains(gcdaFile)) {
// If the object is a .pic.o file and .pic.gcda is not found, we should try finding .gcda too
String picoExt = Iterables.getOnlyElement(CppFileTypes.PIC_OBJECT_FILE.getExtensions());
baseName = FileSystemUtils.replaceExtension(objectFileName, gcdaExt, picoExt);
if (baseName == null) {
// Object file is not .pic.o
return ImmutableList.of();
}
gcdaFile = getNonLipoObjDir(ruleContext, lipoLabel).getRelative(baseName);
if (!gcdaFiles.contains(gcdaFile)) {
// .gcda file not found
return ImmutableList.of();
}
}
return ImmutableList.of(fdoSupportProvider.getGcdaArtifacts().get(gcdaFile));
}
use of com.google.devtools.build.lib.vfs.PathFragment in project bazel by bazelbuild.
the class FdoSupport method extractFdoZip.
/**
* Extracts the FDO zip file and collects data from it that's needed during analysis.
*
* <p>When an {@code --fdo_optimize} compile is requested, unpacks the given
* FDO gcda zip file into a clean working directory under execRoot.
*
* @throws FdoException if the FDO ZIP contains a file of unknown type
*/
private static FdoZipContents extractFdoZip(FdoMode fdoMode, LipoMode lipoMode, Path execRoot, Path fdoProfile, PathFragment fdoRootExecPath, String productName) throws IOException, FdoException {
// The execRoot != null case is only there for testing. We cannot provide a real ZIP file in
// tests because ZipFileSystem does not work with a ZIP on an in-memory file system.
// IMPORTANT: Keep in sync with #declareSkyframeDependencies to avoid incrementality issues.
ImmutableSet<PathFragment> gcdaFiles = ImmutableSet.of();
ImmutableMultimap<PathFragment, PathFragment> imports = ImmutableMultimap.of();
if (fdoProfile != null && execRoot != null) {
Path fdoDirPath = execRoot.getRelative(fdoRootExecPath);
FileSystemUtils.deleteTreesBelow(fdoDirPath);
FileSystemUtils.createDirectoryAndParents(fdoDirPath);
if (fdoMode == FdoMode.AUTO_FDO) {
if (lipoMode != LipoMode.OFF) {
imports = readAutoFdoImports(getAutoFdoImportsPath(fdoProfile));
}
FileSystemUtils.ensureSymbolicLink(execRoot.getRelative(getAutoProfilePath(fdoProfile, fdoRootExecPath)), fdoProfile);
} else if (fdoMode == FdoMode.LLVM_FDO) {
FileSystemUtils.ensureSymbolicLink(execRoot.getRelative(getLLVMProfilePath(fdoProfile, fdoRootExecPath)), fdoProfile);
} else {
Path zipFilePath = new ZipFileSystem(fdoProfile).getRootDirectory();
String outputSymlinkName = productName + "-out";
if (!zipFilePath.getRelative(outputSymlinkName).isDirectory()) {
throw new ZipException("FDO zip files must be zipped directly above '" + outputSymlinkName + "' for the compiler to find the profile");
}
ImmutableSet.Builder<PathFragment> gcdaFilesBuilder = ImmutableSet.builder();
ImmutableMultimap.Builder<PathFragment, PathFragment> importsBuilder = ImmutableMultimap.builder();
extractFdoZipDirectory(zipFilePath, fdoDirPath, gcdaFilesBuilder, importsBuilder);
gcdaFiles = gcdaFilesBuilder.build();
imports = importsBuilder.build();
}
}
return new FdoZipContents(gcdaFiles, imports);
}
Aggregations