/** * 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); }
private CacheResult tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem( BuildRule rule, RuleKey ruleKey, BuildInfoRecorder buildInfoRecorder, ArtifactCache artifactCache, ProjectFilesystem filesystem, BuildContext buildContext) throws InterruptedException { // Create a temp file whose extension must be ".zip" for Filesystems.newFileSystem() to infer // that we are creating a zip-based FileSystem. Path zipFile; try { zipFile = Files.createTempFile( "buck_artifact_" + MoreFiles.sanitize(rule.getBuildTarget().getShortName()), ".zip"); } catch (IOException e) { throw new RuntimeException(e); } // TODO(mbolin): Change ArtifactCache.fetch() so that it returns a File instead of takes one. // Then we could download directly from the remote cache into the on-disk cache and unzip it // from there. CacheResult cacheResult = buildInfoRecorder.fetchArtifactForBuildable(ruleKey, zipFile, artifactCache); if (!cacheResult.getType().isSuccess()) { try { Files.delete(zipFile); } catch (IOException e) { LOG.warn(e, "failed to delete %s", zipFile); } return cacheResult; } // We unzip the file in the root of the project directory. // Ideally, the following would work: // // Path pathToZip = Paths.get(zipFile.getAbsolutePath()); // FileSystem fs = FileSystems.newFileSystem(pathToZip, /* loader */ null); // Path root = Iterables.getOnlyElement(fs.getRootDirectories()); // MoreFiles.copyRecursively(root, projectRoot); // // Unfortunately, this does not appear to work, in practice, because MoreFiles fails when trying // to resolve a Path for a zip entry against a file Path on disk. ArtifactCacheEvent.Started started = ArtifactCacheEvent.started( ArtifactCacheEvent.Operation.DECOMPRESS, ImmutableSet.of(ruleKey)); buildContext.getEventBus().post(started); try { Unzip.extractZipFile( zipFile.toAbsolutePath(), filesystem, Unzip.ExistingFileMode.OVERWRITE_AND_CLEAN_DIRECTORIES); // We only delete the ZIP file when it has been unzipped successfully. Otherwise, we leave it // around for debugging purposes. Files.delete(zipFile); if (cacheResult.getType() == CacheResult.Type.HIT) { // If we have a hit, also write out the build metadata. Path metadataDir = BuildInfo.getPathToMetadataDirectory(rule.getBuildTarget()); for (Map.Entry<String, String> ent : cacheResult.getMetadata().entrySet()) { Path dest = metadataDir.resolve(ent.getKey()); filesystem.createParentDirs(dest); filesystem.writeContentsToPath(ent.getValue(), dest); } } } catch (IOException e) { // In the wild, we have seen some inexplicable failures during this step. For now, we try to // give the user as much information as we can to debug the issue, but return CacheResult.MISS // so that Buck will fall back on doing a local build. buildContext .getEventBus() .post( ConsoleEvent.warning( "Failed to unzip the artifact for %s at %s.\n" + "The rule will be built locally, " + "but here is the stacktrace of the failed unzip call:\n" + rule.getBuildTarget(), zipFile.toAbsolutePath(), Throwables.getStackTraceAsString(e))); return CacheResult.miss(); } finally { buildContext.getEventBus().post(ArtifactCacheEvent.finished(started)); } return cacheResult; }