Пример #1
0
  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();
  }
Пример #2
0
 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);
 }
Пример #3
0
 static PathFragment getSourceDirectoryRelativePathFromResource(Artifact resource) {
   PathFragment resourceDir = LocalResourceContainer.Builder.findResourceDir(resource);
   if (resourceDir == null) {
     return null;
   }
   return trimTo(resource.getRootRelativePath(), resourceDir);
 }
Пример #4
0
  /** 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;
  }
Пример #5
0
 /**
  * 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;
 }
Пример #8
0
  /**
   * 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;
    }
  }
Пример #9
0
 private Artifact getDwoFile(Artifact outputFile) {
   return ruleContext.getRelatedArtifact(outputFile.getRootRelativePath(), ".dwo");
 }
Пример #10
0
  /**
   * 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();
  }
Пример #11
0
 /**
  * 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());
 }