Пример #1
0
 private void addResourceProcessingSteps(
     Path sourcePath, Path destinationPath, ImmutableList.Builder<Step> stepsBuilder) {
   String sourcePathExtension =
       Files.getFileExtension(sourcePath.toString()).toLowerCase(Locale.US);
   switch (sourcePathExtension) {
     case "plist":
     case "stringsdict":
       LOG.debug("Converting plist %s to binary plist %s", sourcePath, destinationPath);
       stepsBuilder.add(
           new PlistProcessStep(
               sourcePath,
               destinationPath,
               ImmutableMap.<String, NSObject>of(),
               ImmutableMap.<String, NSObject>of(),
               PlistProcessStep.OutputFormat.BINARY));
       break;
     case "xib":
       String compiledNibFilename =
           Files.getNameWithoutExtension(destinationPath.toString()) + ".nib";
       Path compiledNibPath = destinationPath.getParent().resolve(compiledNibFilename);
       LOG.debug("Compiling XIB %s to NIB %s", sourcePath, destinationPath);
       stepsBuilder.add(
           new IbtoolStep(ibtool.getCommandPrefix(getResolver()), sourcePath, compiledNibPath));
       break;
     default:
       stepsBuilder.add(CopyStep.forFile(sourcePath, destinationPath));
       break;
   }
 }
Пример #2
0
 @SafeVarargs
 @VisibleForTesting
 static BuckConfig createFromReaders(
     Map<Path, Reader> readers,
     ProjectFilesystem projectFilesystem,
     Platform platform,
     ImmutableMap<String, String> environment,
     ImmutableMap<String, ImmutableMap<String, String>>... configOverrides)
     throws IOException {
   ImmutableList.Builder<ImmutableMap<String, ImmutableMap<String, String>>> builder =
       ImmutableList.builder();
   for (Map.Entry<Path, Reader> entry : readers.entrySet()) {
     Path filePath = entry.getKey();
     Reader reader = entry.getValue();
     ImmutableMap<String, ImmutableMap<String, String>> parsedConfiguration = Inis.read(reader);
     LOG.debug("Loaded a configuration file %s: %s", filePath, parsedConfiguration);
     builder.add(parsedConfiguration);
   }
   for (ImmutableMap<String, ImmutableMap<String, String>> configOverride : configOverrides) {
     LOG.debug("Adding configuration overrides: %s", configOverride);
     builder.add(configOverride);
   }
   Config config = new Config(builder.build());
   return new BuckConfig(config, projectFilesystem, platform, environment);
 }
Пример #3
0
 private static boolean inputFilesUnderSymlink(
     // We use Collection<Path> instead of Iterable<Path> to prevent
     // accidentally passing in Path, since Path itself is Iterable<Path>.
     Collection<Path> inputs,
     ProjectFilesystem projectFilesystem,
     Map<Path, Path> symlinkExistenceCache,
     Map<Path, Path> newSymlinksEncountered)
     throws IOException {
   boolean result = false;
   for (Path input : inputs) {
     for (int i = 1; i < input.getNameCount(); i++) {
       Path subpath = input.subpath(0, i);
       Path resolvedSymlink = symlinkExistenceCache.get(subpath);
       if (resolvedSymlink != null) {
         LOG.debug("Detected cached symlink %s -> %s", subpath, resolvedSymlink);
         newSymlinksEncountered.put(subpath, resolvedSymlink);
         result = true;
       } else if (projectFilesystem.isSymLink(subpath)) {
         Path symlinkTarget = projectFilesystem.resolve(subpath).toRealPath();
         Path relativeSymlinkTarget =
             projectFilesystem.getPathRelativeToProjectRoot(symlinkTarget).or(symlinkTarget);
         LOG.debug("Detected symbolic link %s -> %s", subpath, relativeSymlinkTarget);
         newSymlinksEncountered.put(subpath, relativeSymlinkTarget);
         symlinkExistenceCache.put(subpath, relativeSymlinkTarget);
         result = true;
       }
     }
   }
   return result;
 }
Пример #4
0
  int invalidatePath(Path path) {
    try (AutoCloseableLock writeLock = rawAndComputedNodesLock.writeLock()) {
      int invalidatedRawNodes = 0;
      ImmutableSet<Map<String, Object>> rawNodes = allRawNodes.getIfPresent(path);
      if (rawNodes != null) {
        // Increment the counter
        invalidatedRawNodes = rawNodes.size();
        for (Map<String, Object> rawNode : rawNodes) {
          UnflavoredBuildTarget target =
              RawNodeParsePipeline.parseBuildTargetFromRawRule(cell.getRoot(), rawNode, path);
          LOG.debug("Invalidating target for path %s: %s", path, target);
          for (CacheImpl<?> cache : typedNodeCaches.values()) {
            cache.allComputedNodes.invalidateAll(targetsCornucopia.get(target));
          }
          targetsCornucopia.removeAll(target);
        }
        allRawNodes.invalidate(path);
      }

      // We may have been given a file that other build files depend on. Iteratively remove those.
      Iterable<Path> dependents = buildFileDependents.get(path);
      LOG.debug("Invalidating dependents for path %s: %s", path, dependents);
      for (Path dependent : dependents) {
        if (dependent.equals(path)) {
          continue;
        }
        invalidatedRawNodes += invalidatePath(dependent);
      }
      buildFileDependents.removeAll(path);
      buildFileConfigs.remove(path);

      return invalidatedRawNodes;
    }
  }
Пример #5
0
 private void registerInputsUnderSymlinks(Path buildFile, TargetNode<?> node) throws IOException {
   Map<Path, Path> newSymlinksEncountered = Maps.newHashMap();
   if (inputFilesUnderSymlink(
       node.getInputs(),
       node.getRuleFactoryParams().getProjectFilesystem(),
       symlinkExistenceCache,
       newSymlinksEncountered)) {
     ParserConfig.AllowSymlinks allowSymlinks =
         Preconditions.checkNotNull(
             cellSymlinkAllowability.get(node.getBuildTarget().getCellPath()));
     if (allowSymlinks == ParserConfig.AllowSymlinks.FORBID) {
       throw new HumanReadableException(
           "Target %s contains input files under a path which contains a symbolic link "
               + "(%s). To resolve this, use separate rules and declare dependencies instead of "
               + "using symbolic links.",
           node.getBuildTarget(), newSymlinksEncountered);
     }
     LOG.warn(
         "Disabling caching for target %s, because one or more input files are under a "
             + "symbolic link (%s). This will severely impact performance! To resolve this, use "
             + "separate rules and declare dependencies instead of using symbolic links.",
         node.getBuildTarget(), newSymlinksEncountered);
     buildInputPathsUnderSymlink.add(buildFile);
   }
 }
Пример #6
0
  @Override
  public void close() throws InterruptedException, BuildFileParseException {
    stdout.close();
    stderr.close();

    BuildFileParseException lastSeen = null;
    try {
      closer.close();
    } catch (IOException e) {
      if (e.getCause() instanceof BuildFileParseException) {
        lastSeen = (BuildFileParseException) e.getCause();
      }
      if (e.getCause() instanceof InterruptedException) {
        throw (InterruptedException) e.getCause();
      }
      Throwables.propagate(e);
    }

    LOG.debug(
        "Cleaning cache of build files with inputs under symlink %s", buildInputPathsUnderSymlink);
    Set<Path> buildInputPathsUnderSymlinkCopy = new HashSet<>(buildInputPathsUnderSymlink);
    buildInputPathsUnderSymlink.clear();
    for (Path buildFilePath : buildInputPathsUnderSymlinkCopy) {
      permState.invalidatePath(buildFilePath);
    }

    if (lastSeen != null) {
      throw lastSeen;
    }
  }
Пример #7
0
 /**
  * @param successMessage single line of text without a trailing newline. If stdErr is attached to
  *     a terminal, then this will append an ANSI reset escape sequence followed by a newline.
  */
 public void printSuccess(String successMessage) {
   Preconditions.checkArgument(
       !successMessage.endsWith("\n"), "Trailing newline will be added by this method");
   LOG.debug("Build success: %s", successMessage);
   ansi.printHighlightedSuccessText(stdErr, successMessage);
   stdErr.print('\n');
 }
  public CxxInferCapture createInferCaptureBuildRule(
      BuildTarget target, String name, CxxSource source, CxxInferTools inferTools) {
    Preconditions.checkArgument(CxxSourceTypes.isPreprocessableType(source.getType()));

    LOG.verbose("Creating preprocessed InferCapture build rule %s for %s", target, source);

    CxxInferCapture result =
        new CxxInferCapture(
            getParams()
                .copyWithChanges(
                    target,
                    new DepsBuilder().addPreprocessDeps().add(source),
                    Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
            getPathResolver(),
            CxxToolFlags.copyOf(
                CxxSourceTypes.getPlatformPreprocessFlags(getCxxPlatform(), source.getType()),
                preprocessorFlags.getUnchecked(source.getType())),
            computeCompilerFlags(source.getType(), source.getFlags()),
            source.getPath(),
            source.getType(),
            getCompileOutputPath(target, name),
            getIncludeRoots(),
            getSystemIncludeRoots(),
            getHeaderMaps(),
            getFrameworks(),
            CxxDescriptionEnhancer.frameworkPathToSearchPath(getCxxPlatform(), getPathResolver()),
            getPrefixHeader(),
            inferTools,
            getCxxPlatform().getDebugPathSanitizer());
    getResolver().addToIndex(result);
    return result;
  }
  public static ImmutableSet<ProvisioningProfileMetadata> findProfilesInPath(Path searchPath)
      throws InterruptedException {
    final ImmutableSet.Builder<ProvisioningProfileMetadata> profilesBuilder =
        ImmutableSet.builder();
    try {
      Files.walkFileTree(
          searchPath.toAbsolutePath(),
          new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
              if (file.toString().endsWith(".mobileprovision")) {
                try {
                  ProvisioningProfileMetadata profile =
                      ProvisioningProfileMetadata.fromProvisioningProfilePath(file);
                  profilesBuilder.add(profile);
                } catch (IOException | IllegalArgumentException e) {
                  LOG.error(e, "Ignoring invalid or malformed .mobileprovision file");
                } catch (InterruptedException e) {
                  throw new IOException(e);
                }
              }

              return FileVisitResult.CONTINUE;
            }
          });
    } catch (IOException e) {
      if (e.getCause() instanceof InterruptedException) {
        throw ((InterruptedException) e.getCause());
      }
      LOG.error(e, "Error while searching for mobileprovision files");
    }

    return profilesBuilder.build();
  }
Пример #10
0
/**
 * A step that invokes Apple's tool to scan the binary and copy any needed Swift standard libraries.
 */
public class SwiftStdlibStep implements Step {

  private static final Logger LOG = Logger.get(SwiftStdlibStep.class);

  private final Path workingDirectory;
  private final Iterable<String> command;
  private final Optional<Supplier<CodeSignIdentity>> codeSignIdentitySupplier;

  public SwiftStdlibStep(
      Path workingDirectory,
      Iterable<String> command,
      Optional<Supplier<CodeSignIdentity>> codeSignIdentitySupplier) {
    this.workingDirectory = workingDirectory;
    this.command = command;
    this.codeSignIdentitySupplier = codeSignIdentitySupplier;
  }

  @Override
  public String getShortName() {
    return "copy swift standard libs";
  }

  private ProcessExecutorParams makeProcessExecutorParams() {
    ProcessExecutorParams.Builder builder = ProcessExecutorParams.builder();
    builder.setDirectory(workingDirectory.toAbsolutePath().toFile());
    builder.setCommand(command);
    if (codeSignIdentitySupplier.isPresent()) {
      builder.addCommand(
          "--sign", CodeSignStep.getIdentityArg(codeSignIdentitySupplier.get().get()));
    }
    return builder.build();
  }

  @Override
  public int execute(ExecutionContext context) throws InterruptedException {
    ListeningProcessExecutor executor = new ListeningProcessExecutor();
    ProcessExecutorParams params = makeProcessExecutorParams();
    SimpleProcessListener listener = new SimpleProcessListener();

    // TODO(ryu2): parse output as needed
    try {
      LOG.debug("%s", command);
      ListeningProcessExecutor.LaunchedProcess process = executor.launchProcess(params, listener);
      int result = executor.waitForProcess(process, Long.MAX_VALUE, TimeUnit.SECONDS);
      if (result != 0) {
        LOG.error("Error running %s: %s", getDescription(context), listener.getStderr());
      }
      return result;
    } catch (IOException e) {
      LOG.error(e, "Could not execute command %s", command);
      return 1;
    }
  }

  @Override
  public String getDescription(ExecutionContext context) {
    return Joiner.on(" ").join(command);
  }
}
 private synchronized void invalidateAllCaches() {
   LOG.debug("Invalidating all caches");
   allTargetNodes.invalidateAll();
   targetsCornucopia.clear();
   allRawNodes.invalidateAll();
   buildFileDependents.clear();
   knownCells.clear();
 }
Пример #12
0
 public static int parseAndWriteBuckCompatibleDepfile(
     ExecutionContext context,
     ProjectFilesystem filesystem,
     HeaderPathNormalizer headerPathNormalizer,
     HeaderVerification headerVerification,
     Path sourceDepFile,
     Path destDepFile,
     Path inputPath,
     Path outputPath)
     throws IOException {
   // Process the dependency file, fixing up the paths, and write it out to it's final location.
   // The paths of the headers written out to the depfile are the paths to the symlinks from the
   // root of the repo if the compilation included them from the header search paths pointing to
   // the symlink trees, or paths to headers relative to the source file if the compilation
   // included them using source relative include paths. To handle both cases we check for the
   // prerequisites both in the values and the keys of the replacement map.
   Logger.get(Depfiles.class).debug("Processing dependency file %s as Makefile", sourceDepFile);
   ImmutableMap<String, Object> params =
       ImmutableMap.<String, Object>of("input", inputPath, "output", outputPath);
   try (InputStream input = filesystem.newFileInputStream(sourceDepFile);
       BufferedReader reader = new BufferedReader(new InputStreamReader(input));
       OutputStream output = filesystem.newFileOutputStream(destDepFile);
       BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
       SimplePerfEvent.Scope perfEvent =
           SimplePerfEvent.scope(
               context.getBuckEventBus(), PerfEventId.of("depfile-parse"), params)) {
     ImmutableList<String> prereqs = Depfiles.parseDepfile(reader).getPrereqs();
     // Skip the first prereq, as it's the input source file.
     Preconditions.checkState(inputPath.toString().equals(prereqs.get(0)));
     ImmutableList<String> headers = prereqs.subList(1, prereqs.size());
     for (String rawHeader : headers) {
       Path header = Paths.get(rawHeader).normalize();
       Optional<Path> absolutePath =
           headerPathNormalizer.getAbsolutePathForUnnormalizedPath(header);
       if (absolutePath.isPresent()) {
         Preconditions.checkState(absolutePath.get().isAbsolute());
         writer.write(absolutePath.get().toString());
         writer.newLine();
       } else if (headerVerification.getMode() != HeaderVerification.Mode.IGNORE
           && !headerVerification.isWhitelisted(header.toString())) {
         context
             .getBuckEventBus()
             .post(
                 ConsoleEvent.create(
                     headerVerification.getMode() == HeaderVerification.Mode.ERROR
                         ? Level.SEVERE
                         : Level.WARNING,
                     "%s: included an untracked header \"%s\"",
                     inputPath,
                     header));
         if (headerVerification.getMode() == HeaderVerification.Mode.ERROR) {
           return 1;
         }
       }
     }
   }
   return 0;
 }
  public static Optional<AppleSimulatorProfile> parseProfilePlistStream(InputStream inputStream)
      throws IOException {
    NSDictionary profile;
    try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
      try {
        profile = (NSDictionary) PropertyListParser.parse(bufferedInputStream);
      } catch (Exception e) {
        throw new IOException(e);
      }
    }

    NSObject supportedProductFamilyIDsObject = profile.objectForKey("supportedProductFamilyIDs");
    if (!(supportedProductFamilyIDsObject instanceof NSArray)) {
      LOG.warn(
          "Invalid simulator profile.plist (supportedProductFamilyIDs missing or not an array)");
      return Optional.absent();
    }
    NSArray supportedProductFamilyIDs = (NSArray) supportedProductFamilyIDsObject;

    AppleSimulatorProfile.Builder profileBuilder = AppleSimulatorProfile.builder();
    for (NSObject supportedProductFamilyID : supportedProductFamilyIDs.getArray()) {
      if (supportedProductFamilyID instanceof NSNumber) {
        profileBuilder.addSupportedProductFamilyIDs(
            ((NSNumber) supportedProductFamilyID).intValue());
      } else {
        LOG.warn(
            "Invalid simulator profile.plist (supportedProductFamilyIDs contains non-number %s)",
            supportedProductFamilyID);
        return Optional.absent();
      }
    }

    NSObject supportedArchsObject = profile.objectForKey("supportedArchs");
    if (!(supportedArchsObject instanceof NSArray)) {
      LOG.warn("Invalid simulator profile.plist (supportedArchs missing or not an array)");
      return Optional.absent();
    }
    NSArray supportedArchs = (NSArray) supportedArchsObject;
    for (NSObject supportedArch : supportedArchs.getArray()) {
      profileBuilder.addSupportedArchitectures(supportedArch.toString());
    }

    return Optional.of(profileBuilder.build());
  }
Пример #14
0
  // If multiple valid ones, find the one which matches the most specifically.  I.e.,
  // XXXXXXXXXX.com.example.* will match over XXXXXXXXXX.* for com.example.TestApp
  // TODO(user): Account for differences between development and distribution certificates.
  @VisibleForTesting
  static Optional<ProvisioningProfileMetadata> getBestProvisioningProfile(
      ImmutableSet<ProvisioningProfileMetadata> profiles,
      String bundleID,
      Optional<String> provisioningProfileUUID,
      Optional<String> prefix) {
    int bestMatchLength = -1;
    Optional<ProvisioningProfileMetadata> bestMatch =
        Optional.<ProvisioningProfileMetadata>absent();

    for (ProvisioningProfileMetadata profile : profiles) {
      if (provisioningProfileUUID.isPresent()
          && profile.getUUID().equals(provisioningProfileUUID.get())) {
        return Optional.<ProvisioningProfileMetadata>of(profile);
      }

      if (profile.getExpirationDate().after(new Date())) {
        Pair<String, String> appID = profile.getAppID();

        LOG.debug("Looking at provisioning profile " + profile.getUUID() + "," + appID.toString());

        if (!prefix.isPresent() || prefix.get().equals(appID.getFirst())) {
          String profileBundleID = appID.getSecond();
          boolean match;
          if (profileBundleID.endsWith("*")) {
            // Chop the ending * if wildcard.
            profileBundleID = profileBundleID.substring(0, profileBundleID.length() - 1);
            match = bundleID.startsWith(profileBundleID);
          } else {
            match = (bundleID.equals(profileBundleID));
          }

          if (match && profileBundleID.length() > bestMatchLength) {
            bestMatchLength = profileBundleID.length();
            bestMatch = Optional.<ProvisioningProfileMetadata>of(profile);
          }
        }
      }
    }

    LOG.debug("Found provisioning profile " + bestMatch.toString());
    return bestMatch;
  }
Пример #15
0
  private int doExecute(ExecutionContext context) throws IOException, InterruptedException {
    List<Predicate<Path>> pathPredicates = Lists.newArrayList();

    boolean canDownscale = imageScaler != null && imageScaler.isAvailable(context);
    LOG.info(
        "FilterResourcesStep: canDownscale: %s. imageScalar non-null: %s.",
        canDownscale, imageScaler != null);

    if (filterDrawables) {
      Preconditions.checkNotNull(drawableFinder);
      Set<Path> drawables =
          drawableFinder.findDrawables(inResDirToOutResDirMap.keySet(), filesystem);
      pathPredicates.add(
          ResourceFilters.createImageDensityFilter(
              drawables, Preconditions.checkNotNull(targetDensities), canDownscale));
    }

    final boolean localeFilterEnabled = !locales.isEmpty();
    if (localeFilterEnabled || enableStringWhitelisting) {
      pathPredicates.add(
          new Predicate<Path>() {
            @Override
            public boolean apply(Path path) {
              Matcher matcher =
                  NON_ENGLISH_STRINGS_FILE_PATH.matcher(MorePaths.pathWithUnixSeparators(path));
              if (!matcher.matches()) {
                return true;
              }

              if (enableStringWhitelisting) {
                return isPathWhitelisted(path);
              } else {
                Preconditions.checkState(localeFilterEnabled);
                String locale = matcher.group(1);
                if (matcher.group(2) != null) {
                  locale += "_" + matcher.group(2);
                }

                return locales.contains(locale);
              }
            }
          });
    }

    // Create filtered copies of all resource directories. These will be passed to aapt instead.
    filteredDirectoryCopier.copyDirs(
        filesystem, inResDirToOutResDirMap, Predicates.and(pathPredicates));

    // If an ImageScaler was specified, but only if it is available, try to apply it.
    if (canDownscale && filterDrawables) {
      scaleUnmatchedDrawables(context);
    }

    return 0;
  }
Пример #16
0
  public static Config createDefaultConfig(
      Path root, ImmutableMap<String, ImmutableMap<String, String>> configOverrides)
      throws IOException {
    ImmutableList.Builder<Path> configFileBuilder = ImmutableList.builder();

    configFileBuilder.addAll(listFiles(GLOBAL_BUCK_CONFIG_DIRECTORY_PATH));
    if (Files.isRegularFile(GLOBAL_BUCK_CONFIG_FILE_PATH)) {
      configFileBuilder.add(GLOBAL_BUCK_CONFIG_FILE_PATH);
    }

    Path homeDirectory = Paths.get(System.getProperty("user.home"));
    Path userConfigDir = homeDirectory.resolve(DEFAULT_BUCK_CONFIG_DIRECTORY_NAME);
    configFileBuilder.addAll(listFiles(userConfigDir));
    Path userConfigFile = homeDirectory.resolve(DEFAULT_BUCK_CONFIG_FILE_NAME);
    if (Files.isRegularFile(userConfigFile)) {
      configFileBuilder.add(userConfigFile);
    }

    Path configFile = root.resolve(DEFAULT_BUCK_CONFIG_FILE_NAME);
    if (Files.isRegularFile(configFile)) {
      configFileBuilder.add(configFile);
    }
    Path overrideConfigFile = root.resolve(DEFAULT_BUCK_CONFIG_OVERRIDE_FILE_NAME);
    if (Files.isRegularFile(overrideConfigFile)) {
      configFileBuilder.add(overrideConfigFile);
    }

    ImmutableList<Path> configFiles = configFileBuilder.build();

    ImmutableList.Builder<ImmutableMap<String, ImmutableMap<String, String>>> builder =
        ImmutableList.builder();
    for (Path file : configFiles) {
      try (Reader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
        ImmutableMap<String, ImmutableMap<String, String>> parsedConfiguration = Inis.read(reader);
        LOG.debug("Loaded a configuration file %s: %s", file, parsedConfiguration);
        builder.add(parsedConfiguration);
      }
    }
    LOG.debug("Adding configuration overrides: %s", configOverrides);
    builder.add(configOverrides);
    return new Config(builder.build());
  }
Пример #17
0
  @Override
  public int execute(ExecutionContext context) throws InterruptedException {
    ListeningProcessExecutor executor = new ListeningProcessExecutor();
    ProcessExecutorParams params = makeProcessExecutorParams();
    SimpleProcessListener listener = new SimpleProcessListener();

    // TODO(ryu2): parse output as needed
    try {
      LOG.debug("%s", command);
      ListeningProcessExecutor.LaunchedProcess process = executor.launchProcess(params, listener);
      int result = executor.waitForProcess(process, Long.MAX_VALUE, TimeUnit.SECONDS);
      if (result != 0) {
        LOG.error("Error running %s: %s", getDescription(context), listener.getStderr());
      }
      return result;
    } catch (IOException e) {
      LOG.error(e, "Could not execute command %s", command);
      return 1;
    }
  }
Пример #18
0
  private void executePostBuildSteps(
      BuildRule rule, Iterable<Step> postBuildSteps, BuildContext context)
      throws InterruptedException, StepFailedException {

    LOG.debug("Running post-build steps for %s", rule);

    StepRunner stepRunner = context.getStepRunner();
    Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget());
    for (Step step : postBuildSteps) {
      stepRunner.runStepForBuildTarget(step, optionalTarget);

      // Check for interruptions that may have been ignored by step.
      if (Thread.interrupted()) {
        Thread.currentThread().interrupt();
        throw new InterruptedException();
      }
    }

    LOG.debug("Finished running post-build steps for %s", rule);
  }
  @Override
  public void invalidateBasedOn(WatchEvent<?> event) throws InterruptedException {
    if (!WatchEvents.isPathChangeEvent(event)) {
      // Non-path change event, likely an overflow due to many change events: invalidate everything.
      LOG.debug("Parser invalidating entire cache on overflow.");

      invalidateAllCaches();
      return;
    }

    Path path = (Path) event.context();

    for (Cell cell : knownCells) {
      try {
        if (isPathCreateOrDeleteEvent(event)) {
          BuildFileTree buildFiles = buildFileTrees.get(cell);

          if (path.endsWith(cell.getBuildFileName())) {
            // If a build file has been added or removed, reconstruct the build file tree.
            buildFileTrees.invalidate(cell);
          }

          // Added or removed files can affect globs, so invalidate the package build file
          // "containing" {@code path} unless its filename matches a temp file pattern.
          if (!isTempFile(cell, path)) {
            invalidateContainingBuildFile(cell, buildFiles, path);
          }

          LOG.verbose("Invalidating dependents for path %s, cache state %s", path, this);
        }
      } catch (ExecutionException | UncheckedExecutionException e) {
        try {
          throw propagate(e);
        } catch (BuildFileParseException bfpe) {
          LOG.warn("Unable to parse already parsed build file.", bfpe);
        }
      }
    }

    invalidatePath(path);
  }
Пример #20
0
  private ImmutableBiMap<Path, Path> getAllPaths(Optional<Path> workingDir) {
    if (!workingDir.isPresent()) {
      return other;
    }

    try {
      return pathCache.get(workingDir.get());
    } catch (ExecutionException e) {
      Logger.get(DebugPathSanitizer.class).error("Problem loading paths into cache", e);
      return getAllPathsWork(workingDir.get());
    }
  }
Пример #21
0
  private int handleGet(Request baseRequest, HttpServletResponse response) throws IOException {
    if (!artifactCache.isPresent()) {
      response.getWriter().write("Serving local cache is disabled for this instance.");
      return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
    }

    String path = baseRequest.getUri().getPath();
    String[] pathElements = path.split("/");
    if (pathElements.length != 4 || !pathElements[2].equals("key")) {
      response.getWriter().write("Incorrect url format.");
      return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
    }

    RuleKey ruleKey = RuleKey.TO_RULE_KEY.apply(pathElements[3]);

    Path temp = null;
    try {
      temp =
          projectFilesystem.createTempFile(BuckConstant.SCRATCH_PATH, "outgoing_rulekey", ".tmp");
      projectFilesystem.createParentDirs(temp);
      CacheResult fetchResult;
      try {
        fetchResult = artifactCache.get().fetch(ruleKey, temp);
      } catch (InterruptedException e) {
        LOG.error(e, "Interrupted when fetching from local cache.");
        e.printStackTrace(response.getWriter());
        return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
      }
      if (!fetchResult.getType().isSuccess()) {
        return HttpServletResponse.SC_NOT_FOUND;
      }

      final Path tempFinal = temp;
      HttpArtifactCacheBinaryProtocol.FetchResponse fetchResponse =
          new HttpArtifactCacheBinaryProtocol.FetchResponse(
              ImmutableSet.of(ruleKey),
              fetchResult.getMetadata(),
              new ByteSource() {
                @Override
                public InputStream openStream() throws IOException {
                  return projectFilesystem.newFileInputStream(tempFinal);
                }
              });
      fetchResponse.write(response.getOutputStream());
      response.setContentLengthLong(fetchResponse.getContentLength());
      return HttpServletResponse.SC_OK;
    } finally {
      if (temp != null) {
        projectFilesystem.deleteFileAtPathIfExists(temp);
      }
    }
  }
Пример #22
0
 @Override
 public int execute(ExecutionContext context) {
   try (InputStream sourceStream = source.openStream()) {
     context
         .getProjectFilesystem()
         .copyToPath(sourceStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
     return 0;
   } catch (IOException e) {
     LOG.error(e, "Couldn't copy bytes to %s", outputPath);
     e.printStackTrace(context.getStdErr());
     return 1;
   }
 }
Пример #23
0
  public static CxxPlatform getConfigDefaultCxxPlatform(
      CxxBuckConfig cxxBuckConfig,
      ImmutableMap<Flavor, CxxPlatform> cxxPlatformsMap,
      CxxPlatform systemDefaultCxxPlatform) {
    CxxPlatform defaultCxxPlatform;
    Optional<String> defaultPlatform = cxxBuckConfig.getDefaultPlatform();
    if (defaultPlatform.isPresent()) {
      defaultCxxPlatform = cxxPlatformsMap.get(ImmutableFlavor.of(defaultPlatform.get()));
      if (defaultCxxPlatform == null) {
        LOG.warn(
            "Couldn't find default platform %s, falling back to system default",
            defaultPlatform.get());
      } else {
        LOG.debug("Using config default C++ platform %s", defaultCxxPlatform);
        return defaultCxxPlatform;
      }
    } else {
      LOG.debug("Using system default C++ platform %s", systemDefaultCxxPlatform);
    }

    return systemDefaultCxxPlatform;
  }
Пример #24
0
public class WriteFileStep implements Step {

  private static final Logger LOG = Logger.get(WriteFileStep.class);
  private final ByteSource source;
  private final Path outputPath;

  public WriteFileStep(ByteSource content, Path outputPath) {
    this.source = content;
    this.outputPath = outputPath;
  }

  public WriteFileStep(String content, Path outputPath) {
    this(Suppliers.ofInstance(content), outputPath);
  }

  public WriteFileStep(final Supplier<String> content, Path outputPath) {
    this(
        new ByteSource() {
          @Override
          public InputStream openStream() throws IOException {
            // echo by default writes a trailing new line and so should we.
            return new ByteArrayInputStream((content.get() + "\n").getBytes(Charsets.UTF_8));
          }
        },
        outputPath);
  }

  @Override
  public int execute(ExecutionContext context) {
    try (InputStream sourceStream = source.openStream()) {
      context
          .getProjectFilesystem()
          .copyToPath(sourceStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
      return 0;
    } catch (IOException e) {
      LOG.error(e, "Couldn't copy bytes to %s", outputPath);
      e.printStackTrace(context.getStdErr());
      return 1;
    }
  }

  @Override
  public String getShortName() {
    return "write_file";
  }

  @Override
  public String getDescription(ExecutionContext context) {
    return String.format("echo ... > %s", Escaper.escapeAsBashString(outputPath));
  }
}
Пример #25
0
  private static void buildAppleCxxPlatforms(
      Supplier<Optional<Path>> appleDeveloperDirectorySupplier,
      ImmutableList<Path> extraToolchainPaths,
      ImmutableList<Path> extraPlatformPaths,
      BuckConfig buckConfig,
      AppleConfig appleConfig,
      ImmutableMap.Builder<Flavor, AppleCxxPlatform> platformFlavorsToAppleSdkPathsBuilder)
      throws IOException {
    Optional<Path> appleDeveloperDirectory = appleDeveloperDirectorySupplier.get();
    if (appleDeveloperDirectory.isPresent() && !Files.isDirectory(appleDeveloperDirectory.get())) {
      LOG.error(
          "Developer directory is set to %s, but is not a directory",
          appleDeveloperDirectory.get());
      return;
    }

    ImmutableMap<String, AppleToolchain> toolchains =
        AppleToolchainDiscovery.discoverAppleToolchains(
            appleDeveloperDirectory, extraToolchainPaths);

    ImmutableMap<AppleSdk, AppleSdkPaths> sdkPaths =
        AppleSdkDiscovery.discoverAppleSdkPaths(
            appleDeveloperDirectory, extraPlatformPaths, toolchains);

    for (Map.Entry<AppleSdk, AppleSdkPaths> entry : sdkPaths.entrySet()) {
      AppleSdk sdk = entry.getKey();
      AppleSdkPaths appleSdkPaths = entry.getValue();
      String targetSdkVersion =
          appleConfig.getTargetSdkVersion(sdk.getApplePlatform()).or(sdk.getVersion());
      LOG.debug("SDK %s using default version %s", sdk, targetSdkVersion);
      for (String architecture : sdk.getArchitectures()) {
        AppleCxxPlatform appleCxxPlatform =
            AppleCxxPlatforms.build(sdk, targetSdkVersion, architecture, appleSdkPaths, buckConfig);
        platformFlavorsToAppleSdkPathsBuilder.put(
            appleCxxPlatform.getCxxPlatform().getFlavor(), appleCxxPlatform);
      }
    }
  }
Пример #26
0
  @Override
  public boolean fetch(BuckEventBus eventBus, URI uri, Path output) throws IOException {
    for (Downloader downloader : delegates) {
      try {
        if (downloader.fetch(eventBus, uri, output)) {
          return true;
        }
      } catch (IOException e) {
        LOG.debug(e, "Unable to download %s from %s", uri, downloader);
      }
    }

    return false;
  }
Пример #27
0
  /**
   * Execute the commands for this build rule. Requires all dependent rules are already built
   * successfully.
   */
  private void executeCommandsNowThatDepsAreBuilt(
      BuildRule rule,
      BuildContext context,
      BuildableContext buildableContext,
      BuildInfoRecorder buildInfoRecorder)
      throws InterruptedException, StepFailedException {

    LOG.debug("Building locally: %s", rule);
    // Attempt to get an approximation of how long it takes to actually run the command.
    @SuppressWarnings("PMD.PrematureDeclaration")
    long start = System.nanoTime();

    // Get and run all of the commands.
    List<Step> steps = rule.getBuildSteps(context, buildableContext);

    AbiRule abiRule = checkIfRuleOrBuildableIsAbiRule(rule);
    if (abiRule != null) {
      buildInfoRecorder.addBuildMetadata(
          ABI_KEY_FOR_DEPS_ON_DISK_METADATA, abiRule.getAbiKeyForDeps().getHash());
    }

    StepRunner stepRunner = context.getStepRunner();
    Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget());
    for (Step step : steps) {
      stepRunner.runStepForBuildTarget(step, optionalTarget);

      // Check for interruptions that may have been ignored by step.
      if (Thread.interrupted()) {
        Thread.currentThread().interrupt();
        throw new InterruptedException();
      }
    }

    long end = System.nanoTime();
    LOG.debug(
        "Build completed: %s %s (%dns)", rule.getType(), rule.getFullyQualifiedName(), end - start);
  }
Пример #28
0
  @Override
  public int runWithoutHelp(final CommandRunnerParams params)
      throws IOException, InterruptedException {
    // Create a TargetGraph that is composed of the transitive closure of all of the dependent
    // TargetNodes for the specified BuildTargets.
    final ImmutableSet<String> fullyQualifiedBuildTargets =
        ImmutableSet.copyOf(getArgumentsFormattedAsBuildTargets(params.getBuckConfig()));

    if (fullyQualifiedBuildTargets.isEmpty()) {
      params.getConsole().printBuildFailure("Please specify at least one build target.");
      return 1;
    }

    ImmutableSet<BuildTarget> targets =
        FluentIterable.from(getArgumentsFormattedAsBuildTargets(params.getBuckConfig()))
            .transform(
                new Function<String, BuildTarget>() {
                  @Override
                  public BuildTarget apply(String input) {
                    return BuildTargetParser.INSTANCE.parse(
                        input, BuildTargetPatternParser.fullyQualified());
                  }
                })
            .toSet();

    LOG.debug("Getting input for targets: %s", targets);

    TargetGraph graph;
    try {
      graph =
          params
              .getParser()
              .buildTargetGraphForBuildTargets(
                  targets,
                  new ParserConfig(params.getBuckConfig()),
                  params.getBuckEventBus(),
                  params.getConsole(),
                  params.getEnvironment(),
                  getEnableProfiling());
    } catch (BuildTargetException | BuildFileParseException e) {
      params.getConsole().printBuildFailureWithoutStacktrace(e);
      return 1;
    }

    if (shouldGenerateJsonOutput()) {
      return printJsonInputs(params, graph);
    }
    return printInputs(params, graph);
  }
Пример #29
0
 /**
  * Attempt to complete submitted requests on close so that as much information is recorded as
  * possible. This aids debugging when close is called during exception processing.
  */
 @Override
 public void close() {
   requestService.shutdown();
   try {
     if (!requestService.awaitTermination(timeoutMillis, TimeUnit.MILLISECONDS)) {
       LOG.warn(
           Joiner.on(System.lineSeparator())
               .join(
                   "A BlockingHttpEndpoint failed to shut down within the standard timeout.",
                   "Your build might have succeeded, but some requests made to ",
                   this.url + " were probably lost.",
                   "Here's some debugging information:",
                   requestService.toString()));
     }
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
   }
 }
Пример #30
0
 /**
  * {@link ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)} is called to wait
  * for events which have been posted, but which have been queued by the {@link EventBus}, to be
  * delivered. This allows listeners to record or report as much information as possible. This aids
  * debugging when close is called during exception processing.
  */
 @Override
 public void close() throws IOException {
   executorService.shutdown();
   try {
     if (!executorService.awaitTermination(shutdownTimeoutMillis, TimeUnit.MILLISECONDS)) {
       LOG.warn(
           Joiner.on(System.lineSeparator())
               .join(
                   "The BuckEventBus failed to shut down within the standard timeout.",
                   "Your build might have succeeded, but some messages were probably lost.",
                   "Here's some debugging information:",
                   executorService.toString()));
       executorService.shutdownNow();
     }
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
   }
 }