private ImmutableList<Artifact> generatedOutputArtifacts(FileType newFileType) { ImmutableList.Builder<Artifact> builder = new ImmutableList.Builder<>(); for (Artifact protoFile : getFilteredProtoSources()) { String protoFileName = FileSystemUtils.removeExtension(protoFile.getFilename()); String generatedOutputName; if (attributes.outputsCpp()) { generatedOutputName = protoFileName; } else if (usesProtobufLibrary()) { // The protobuf library generates filenames with some slight modifications. generatedOutputName = generateProtobufFilename(protoFileName); } else { String lowerUnderscoreBaseName = protoFileName.replace('-', '_').toLowerCase(); generatedOutputName = LOWER_UNDERSCORE.to(UPPER_CAMEL, lowerUnderscoreBaseName); } PathFragment generatedFilePath = new PathFragment( protoFile.getRootRelativePath().getParentDirectory(), new PathFragment(generatedOutputName)); PathFragment outputFile = FileSystemUtils.appendExtension(generatedFilePath, newFileType.getExtensions().get(0)); if (outputFile != null) { builder.add( ruleContext.getUniqueDirectoryArtifact( UNIQUE_DIRECTORY_NAME, outputFile, ruleContext.getBinOrGenfilesDirectory())); } } return builder.build(); }
private Artifact inUniqueObjsDir(Artifact source, String extension) { PathFragment uniqueDir = new PathFragment("_objs").getRelative(ruleContext.getLabel().getName()); PathFragment sourceFile = uniqueDir.getRelative(source.getRootRelativePath()); PathFragment scopeRelativePath = FileSystemUtils.replaceExtension(sourceFile, extension); return scopedArtifact(scopeRelativePath); }
static PathFragment getSourceDirectoryRelativePathFromResource(Artifact resource) { PathFragment resourceDir = LocalResourceContainer.Builder.findResourceDir(resource); if (resourceDir == null) { return null; } return trimTo(resource.getRootRelativePath(), resourceDir); }
/** Registers an action to generate a runner script based on a template. */ ReleaseBundlingSupport registerGenerateRunnerScriptAction( Artifact runnerScript, Artifact ipaInput) { ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); String escapedSimDevice = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorDevice()); String escapedSdkVersion = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorVersion()); ImmutableList<Substitution> substitutions = ImmutableList.of( Substitution.of("%app_name%", ruleContext.getLabel().getName()), Substitution.of("%ipa_file%", ipaInput.getRootRelativePath().getPathString()), Substitution.of("%sim_device%", escapedSimDevice), Substitution.of("%sdk_version%", escapedSdkVersion), Substitution.of("%iossim%", attributes.iossim().getRootRelativePath().getPathString()), Substitution.of( "%std_redirect_dylib_path%", attributes.stdRedirectDylib().getRootRelativePath().getPathString())); ruleContext.registerAction( new TemplateExpansionAction( ruleContext.getActionOwner(), attributes.runnerScriptTemplate(), runnerScript, substitutions, true)); return this; }
/** * The artifact for the .o file that should be generated when compiling the {@code source} * artifact. */ public Artifact objFile(Artifact source) { if (source.isTreeArtifact()) { PathFragment rootRelativePath = source.getRootRelativePath().replaceName("obj_files"); return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory()); } else { return inUniqueObjsDir(source, ".o"); } }
/** * Retrieves the asset {@link Artifact} and asset root {@link PathFragment}. * * @param assetsDir The common directory for the assets, used to get the directory roots and * verify the artifacts are located beneath the assetsDir * @param targets {@link FileProvider}s for a given set of assets. * @return The Builder. */ public LocalResourceContainer.Builder withAssets( PathFragment assetsDir, Iterable<? extends TransitiveInfoCollection> targets) { for (TransitiveInfoCollection target : targets) { for (Artifact file : target.getProvider(FileProvider.class).getFilesToBuild()) { PathFragment packageFragment = file.getArtifactOwner().getLabel().getPackageIdentifier().getSourceRoot(); PathFragment packageRelativePath = file.getRootRelativePath().relativeTo(packageFragment); if (packageRelativePath.startsWith(assetsDir)) { PathFragment relativePath = packageRelativePath.relativeTo(assetsDir); assetRoots.add(trimTail(file.getExecPath(), relativePath)); } else { ruleContext.attributeError( ResourceType.ASSETS.getAttribute(), String.format( "'%s' (generated by '%s') is not beneath '%s'", file.getRootRelativePath(), target.getLabel(), assetsDir)); return this; } assets.add(file); } } return this; }
/** * Retrieves the resource {@link Artifact} and resource root {@link PathFragment}. * * @param targets {@link FileProvider}s for a given set of resource. * @return The Builder. */ public LocalResourceContainer.Builder withResources(Iterable<FileProvider> targets) { PathFragment lastResourceDir = null; Artifact lastFile = null; for (FileProvider target : targets) { for (Artifact file : target.getFilesToBuild()) { PathFragment packageFragment = file.getArtifactOwner().getLabel().getPackageIdentifier().getSourceRoot(); PathFragment packageRelativePath = file.getRootRelativePath().relativeTo(packageFragment); PathFragment resourceDir = findResourceDir(file); if (resourceDir == null) { ruleContext.attributeError( ResourceType.RESOURCES.getAttribute(), String.format(INCORRECT_RESOURCE_LAYOUT_MESSAGE, file.getRootRelativePath())); return this; } if (lastResourceDir == null || resourceDir.equals(lastResourceDir)) { resourceRoots.add( trimTail(file.getExecPath(), makeRelativeTo(resourceDir, packageRelativePath))); } else { ruleContext.attributeError( ResourceType.RESOURCES.getAttribute(), String.format( "'%s' (generated by '%s') is not in the same directory '%s' (derived from %s)." + " All resources must share a common directory.", file.getRootRelativePath(), file.getArtifactOwner().getLabel(), lastResourceDir, lastFile.getRootRelativePath())); return this; } resources.add(file); lastFile = file; lastResourceDir = resourceDir; } } return this; }
/** * Returns the .dwo output file that matches the specified .o output file. If Fission mode isn't * enabled for this build, this is null (we don't produce .dwo files in that case). */ private static Artifact getDwoFile( RuleContext ruleContext, Artifact outputFile, CppConfiguration cppConfiguration) { // Only create .dwo's for .o compilations (i.e. not .ii or .S). boolean isObjectOutput = CppFileTypes.OBJECT_FILE.matches(outputFile.getExecPath()) || CppFileTypes.PIC_OBJECT_FILE.matches(outputFile.getExecPath()); // Note configurations can be null for tests. if (cppConfiguration != null && cppConfiguration.useFission() && isObjectOutput) { return ruleContext.getRelatedArtifact(outputFile.getRootRelativePath(), ".dwo"); } else { return null; } }
private Artifact getDwoFile(Artifact outputFile) { return ruleContext.getRelatedArtifact(outputFile.getRootRelativePath(), ".dwo"); }
/** * Constructs the C++ linker actions. It generally generates two actions, one for a static library * and one for a dynamic library. If PIC is required for shared libraries, but not for binaries, * it additionally creates a third action to generate a PIC static library. * * <p>For dynamic libraries, this method can additionally create an interface shared library that * can be used for linking, but doesn't contain any executable code. This increases the number of * cache hits for link actions. Call {@link #setAllowInterfaceSharedObjects(boolean)} to enable * this behavior. * * @throws RuleErrorException */ public CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs) throws RuleErrorException { // For now only handle static links. Note that the dynamic library link below ignores linkType. // TODO(bazel-team): Either support non-static links or move this check to setLinkType(). Preconditions.checkState(linkType.isStaticLibraryLink(), "can only handle static links"); CcLinkingOutputs.Builder result = new CcLinkingOutputs.Builder(); if (cppConfiguration.isLipoContextCollector()) { // Don't try to create LIPO link actions in collector mode, // because it needs some data that's not available at this point. return result.build(); } AnalysisEnvironment env = ruleContext.getAnalysisEnvironment(); boolean usePicForBinaries = CppHelper.usePic(ruleContext, true); boolean usePicForSharedLibs = CppHelper.usePic(ruleContext, false); // Create static library (.a). The linkType only reflects whether the library is alwayslink or // not. The PIC-ness is determined by whether we need to use PIC or not. There are three cases // for (usePicForSharedLibs usePicForBinaries): // // (1) (false false) -> no pic code // (2) (true false) -> shared libraries as pic, but not binaries // (3) (true true) -> both shared libraries and binaries as pic // // In case (3), we always need PIC, so only create one static library containing the PIC object // files. The name therefore does not match the content. // // Presumably, it is done this way because the .a file is an implicit output of every cc_library // rule, so we can't use ".pic.a" that in the always-PIC case. // If the crosstool is configured to select an output artifact, we use that selection. // Otherwise, we use linux defaults. Artifact linkedArtifact = getLinkedArtifact(linkType); CppLinkAction maybePicAction = newLinkActionBuilder(linkedArtifact) .addNonLibraryInputs(ccOutputs.getObjectFiles(usePicForBinaries)) .addNonLibraryInputs(ccOutputs.getHeaderTokenFiles()) .addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()) .setLinkType(linkType) .setLinkStaticness(LinkStaticness.FULLY_STATIC) .setFeatureConfiguration(featureConfiguration) .build(); env.registerAction(maybePicAction); result.addStaticLibrary(maybePicAction.getOutputLibrary()); // Create a second static library (.pic.a). Only in case (2) do we need both PIC and non-PIC // static libraries. In that case, the first static library contains the non-PIC code, and this // one contains the PIC code, so the names match the content. if (!usePicForBinaries && usePicForSharedLibs) { LinkTargetType picLinkType = (linkType == LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY) ? LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY : LinkTargetType.PIC_STATIC_LIBRARY; // If the crosstool is configured to select an output artifact, we use that selection. // Otherwise, we use linux defaults. Artifact picArtifact = getLinkedArtifact(picLinkType); CppLinkAction picAction = newLinkActionBuilder(picArtifact) .addNonLibraryInputs(ccOutputs.getObjectFiles(true)) .addNonLibraryInputs(ccOutputs.getHeaderTokenFiles()) .addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()) .setLinkType(picLinkType) .setLinkStaticness(LinkStaticness.FULLY_STATIC) .setFeatureConfiguration(featureConfiguration) .build(); env.registerAction(picAction); result.addPicStaticLibrary(picAction.getOutputLibrary()); } if (!createDynamicLibrary) { return result.build(); } // Create dynamic library. Artifact soImpl; if (soImplArtifact == null) { // If the crosstool is configured to select an output artifact, we use that selection. // Otherwise, we use linux defaults. soImpl = getLinkedArtifact(LinkTargetType.DYNAMIC_LIBRARY); } else { soImpl = soImplArtifact; } List<String> sonameLinkopts = ImmutableList.of(); Artifact soInterface = null; if (cppConfiguration.useInterfaceSharedObjects() && allowInterfaceSharedObjects) { soInterface = CppHelper.getLinuxLinkedArtifact(ruleContext, LinkTargetType.INTERFACE_DYNAMIC_LIBRARY); sonameLinkopts = ImmutableList.of( "-Wl,-soname=" + SolibSymlinkAction.getDynamicLibrarySoname( soImpl.getRootRelativePath(), false)); } // Should we also link in any libraries that this library depends on? // That is required on some systems... CppLinkActionBuilder linkActionBuilder = newLinkActionBuilder(soImpl) .setInterfaceOutput(soInterface) .addNonLibraryInputs(ccOutputs.getObjectFiles(usePicForSharedLibs)) .addNonLibraryInputs(ccOutputs.getHeaderTokenFiles()) .addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()) .setLinkType(LinkTargetType.DYNAMIC_LIBRARY) .setLinkStaticness(LinkStaticness.DYNAMIC) .addLinkopts(linkopts) .addLinkopts(sonameLinkopts) .setRuntimeInputs( CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkMiddleman(), CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkInputs()) .setFeatureConfiguration(featureConfiguration); if (!ccOutputs.getLtoBitcodeFiles().isEmpty() && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) { linkActionBuilder.setLTOIndexing(true); CppLinkAction indexAction = linkActionBuilder.build(); env.registerAction(indexAction); for (LTOBackendArtifacts ltoArtifacts : indexAction.getAllLTOBackendArtifacts()) { ltoArtifacts.scheduleLTOBackendAction(ruleContext, usePicForSharedLibs); } linkActionBuilder.setLTOIndexing(false); } CppLinkAction action = linkActionBuilder.build(); env.registerAction(action); LibraryToLink dynamicLibrary = action.getOutputLibrary(); LibraryToLink interfaceLibrary = action.getInterfaceOutputLibrary(); if (interfaceLibrary == null) { interfaceLibrary = dynamicLibrary; } // If shared library has neverlink=1, then leave it untouched. Otherwise, // create a mangled symlink for it and from now on reference it through // mangled name only. if (neverLink) { result.addDynamicLibrary(interfaceLibrary); result.addExecutionDynamicLibrary(dynamicLibrary); } else { LibraryToLink libraryLink = SolibSymlinkAction.getDynamicLibrarySymlink( ruleContext, interfaceLibrary.getArtifact(), false, false, ruleContext.getConfiguration()); result.addDynamicLibrary(libraryLink); LibraryToLink implLibraryLink = SolibSymlinkAction.getDynamicLibrarySymlink( ruleContext, dynamicLibrary.getArtifact(), false, false, ruleContext.getConfiguration()); result.addExecutionDynamicLibrary(implLibraryLink); } return result.build(); }
/** * Returns a static library archive with dead code/objects removed by J2ObjC dead code removal, * given the original unpruned static library containing J2ObjC-translated code. */ public Artifact j2objcPrunedArchive(Artifact unprunedArchive) { PathFragment prunedSourceArtifactPath = FileSystemUtils.appendWithoutExtension(unprunedArchive.getRootRelativePath(), "_pruned"); return ruleContext.getUniqueDirectoryArtifact( "_j2objc_pruned", prunedSourceArtifactPath, ruleContext.getBinOrGenfilesDirectory()); }
private static ArtifactLocation makeArtifactLocation(Artifact artifact) { return makeArtifactLocation(artifact.getRoot(), artifact.getRootRelativePath()); }