use of com.google.devtools.build.lib.vfs.Path in project bazel by bazelbuild.
the class AndroidNdkRepositoryFunction method fetch.
@Override
public RepositoryDirectoryValue.Builder fetch(Rule rule, Path outputDirectory, BlazeDirectories directories, Environment env, Map<String, String> markerData) throws InterruptedException, RepositoryFunctionException {
Map<String, String> environ = declareEnvironmentDependencies(markerData, env, PATH_ENV_VAR_AS_LIST);
if (environ == null) {
return null;
}
prepareLocalRepositorySymlinkTree(rule, outputDirectory);
WorkspaceAttributeMapper attributes = WorkspaceAttributeMapper.of(rule);
PathFragment pathFragment;
if (attributes.isAttributeValueExplicitlySpecified("path")) {
pathFragment = getTargetPath(rule, directories.getWorkspace());
} else if (environ.get(PATH_ENV_VAR) != null) {
pathFragment = getAndroidNdkHomeEnvironmentVar(directories.getWorkspace(), environ);
} else {
throw new RepositoryFunctionException(new EvalException(rule.getLocation(), "Either the path attribute of android_ndk_repository or the ANDROID_NDK_HOME " + " environment variable must be set."), Transience.PERSISTENT);
}
Path ndkSymlinkTreeDirectory = outputDirectory.getRelative("ndk");
try {
ndkSymlinkTreeDirectory.createDirectory();
} catch (IOException e) {
throw new RepositoryFunctionException(e, Transience.TRANSIENT);
}
Path ndkHome = directories.getOutputBase().getFileSystem().getPath(pathFragment);
if (!symlinkLocalRepositoryContents(ndkSymlinkTreeDirectory, ndkHome)) {
return null;
}
String ruleName = rule.getName();
// We need to fetch the NDK release info from the actual home to avoid cycle in the
// dependency graph (the path relative to the repository root depends on the
// repository being fetched).
NdkRelease ndkRelease = getNdkRelease(ndkHome, env);
if (env.valuesMissing()) {
return null;
}
String apiLevelString;
if (attributes.isAttributeValueExplicitlySpecified("api_level")) {
try {
apiLevelString = attributes.get("api_level", Type.INTEGER).toString();
} catch (EvalException e) {
throw new RepositoryFunctionException(e, Transience.PERSISTENT);
}
} else {
DirectoryListingValue platformsDirectoryValue = AndroidRepositoryUtils.getDirectoryListing(ndkHome, PLATFORMS_DIR, env);
if (platformsDirectoryValue == null) {
return null;
}
ImmutableSortedSet<Integer> apiLevels = AndroidRepositoryUtils.getApiLevels(platformsDirectoryValue.getDirents());
if (apiLevels.isEmpty()) {
// themselves.
throw new RepositoryFunctionException(new EvalException(rule.getLocation(), "android_ndk_repository requires that at least one Android platform is present in " + "the Android NDK platforms directory. Please ensure that the path attribute " + "or the ANDROID_NDK_HOME environment variable points to a valid NDK."), Transience.PERSISTENT);
}
apiLevelString = apiLevels.first().toString();
}
// NDK minor revisions should be backwards compatible within a major revision, the crosstools
// we generate don't care about the minor revision.
NdkMajorRevision ndkMajorRevision;
if (!ndkRelease.isValid) {
String warningMessage = String.format("The revision of the Android NDK referenced by android_ndk_repository rule '%s' " + "could not be determined (the revision string found is '%s'). Defaulting to " + "revision %s.", ruleName, ndkRelease.rawRelease, AndroidNdkCrosstools.LATEST_KNOWN_REVISION.getKey());
env.getListener().handle(Event.warn(warningMessage));
ndkMajorRevision = AndroidNdkCrosstools.LATEST_KNOWN_REVISION.getValue();
} else if (!AndroidNdkCrosstools.isKnownNDKRevision(ndkRelease)) {
String warningMessage = String.format("The major revision of the Android NDK referenced by android_ndk_repository rule " + "'%s' is %s. The major revisions supported by Bazel are %s. Defaulting to " + "revision %s.", ruleName, ndkRelease.majorRevision, AndroidNdkCrosstools.KNOWN_NDK_MAJOR_REVISIONS.keySet(), AndroidNdkCrosstools.LATEST_KNOWN_REVISION.getKey());
env.getListener().handle(Event.warn(warningMessage));
ndkMajorRevision = AndroidNdkCrosstools.LATEST_KNOWN_REVISION.getValue();
} else {
ndkMajorRevision = AndroidNdkCrosstools.KNOWN_NDK_MAJOR_REVISIONS.get(ndkRelease.majorRevision);
}
ApiLevel apiLevel = ndkMajorRevision.apiLevel(env.getListener(), ruleName, apiLevelString);
ImmutableList.Builder<CrosstoolStlPair> crosstoolsAndStls = ImmutableList.builder();
try {
String hostPlatform = AndroidNdkCrosstools.getHostPlatform(ndkRelease);
NdkPaths ndkPaths = new NdkPaths(ruleName, hostPlatform, apiLevel);
for (StlImpl stlImpl : StlImpls.get(ndkPaths)) {
CrosstoolRelease crosstoolRelease = ndkMajorRevision.crosstoolRelease(ndkPaths, stlImpl, hostPlatform);
crosstoolsAndStls.add(new CrosstoolStlPair(crosstoolRelease, stlImpl));
}
} catch (NdkCrosstoolsException e) {
throw new RepositoryFunctionException(new IOException(e), Transience.PERSISTENT);
}
String buildFile = createBuildFile(ruleName, crosstoolsAndStls.build());
writeBuildFile(outputDirectory, buildFile);
return RepositoryDirectoryValue.builder().setPath(outputDirectory);
}
use of com.google.devtools.build.lib.vfs.Path in project bazel by bazelbuild.
the class AndroidNdkRepositoryFunction method getNdkRelease.
private static NdkRelease getNdkRelease(Path directory, Environment env) throws RepositoryFunctionException, InterruptedException {
// For NDK r11+
Path releaseFilePath = directory.getRelative("source.properties");
if (!releaseFilePath.exists()) {
// For NDK r10e
releaseFilePath = directory.getRelative("RELEASE.TXT");
}
SkyKey releaseFileKey = FileValue.key(RootedPath.toRootedPath(directory, releaseFilePath));
String releaseFileContent;
try {
env.getValueOrThrow(releaseFileKey, IOException.class, FileSymlinkException.class, InconsistentFilesystemException.class);
releaseFileContent = new String(FileSystemUtils.readContent(releaseFilePath));
} catch (IOException | FileSymlinkException | InconsistentFilesystemException e) {
throw new RepositoryFunctionException(new IOException("Could not read " + releaseFilePath.getBaseName() + " in Android NDK: " + e.getMessage()), Transience.PERSISTENT);
}
return NdkRelease.create(releaseFileContent.trim());
}
use of com.google.devtools.build.lib.vfs.Path in project bazel by bazelbuild.
the class StandaloneTestStrategy method exec.
@Override
public void exec(TestRunnerAction action, ActionExecutionContext actionExecutionContext) throws ExecException, InterruptedException {
Path execRoot = actionExecutionContext.getExecutor().getExecRoot();
Path coverageDir = execRoot.getRelative(action.getCoverageDirectory());
Path runfilesDir = getLocalRunfilesDirectory(action, actionExecutionContext, binTools, action.getLocalShellEnvironment(), action.isEnableRunfiles());
Path tmpDir = tmpDirRoot.getChild(getTmpDirName(action.getExecutionSettings().getExecutable().getExecPath()));
Map<String, String> env = setupEnvironment(action, execRoot, runfilesDir, tmpDir);
Path workingDirectory = runfilesDir.getRelative(action.getRunfilesPrefix());
ResolvedPaths resolvedPaths = action.resolve(execRoot);
Map<String, String> info = new HashMap<>();
// This key is only understood by StandaloneSpawnStrategy.
info.put("timeout", "" + getTimeout(action));
info.putAll(action.getTestProperties().getExecutionInfo());
Spawn spawn = new SimpleSpawn(action, getArgs(COLLECT_COVERAGE, action), ImmutableMap.copyOf(env), ImmutableMap.copyOf(info), new RunfilesSupplierImpl(runfilesDir.asFragment(), action.getExecutionSettings().getRunfiles()), /*inputs=*/
ImmutableList.copyOf(action.getInputs()), /*tools=*/
ImmutableList.<Artifact>of(), /*filesetManifests=*/
ImmutableList.<Artifact>of(), ImmutableList.copyOf(action.getSpawnOutputs()), action.getTestProperties().getLocalResourceUsage(executionOptions.usingLocalTestJobs()));
Executor executor = actionExecutionContext.getExecutor();
TestResultData.Builder dataBuilder = TestResultData.newBuilder();
try {
int maxAttempts = getTestAttempts(action);
TestResultData data = executeTestAttempt(action, spawn, actionExecutionContext, execRoot, coverageDir, tmpDir, workingDirectory);
int attempt;
for (attempt = 1; data.getStatus() != BlazeTestStatus.PASSED && attempt < maxAttempts; attempt++) {
processFailedTestAttempt(attempt, executor, action, dataBuilder, data, actionExecutionContext.getFileOutErr());
data = executeTestAttempt(action, spawn, actionExecutionContext, execRoot, coverageDir, tmpDir, workingDirectory);
}
processLastTestAttempt(attempt, dataBuilder, data);
ImmutableList.Builder<Pair<String, Path>> testOutputsBuilder = new ImmutableList.Builder<>();
if (action.getTestLog().getPath().exists()) {
testOutputsBuilder.add(Pair.of("test.log", action.getTestLog().getPath()));
}
if (resolvedPaths.getXmlOutputPath().exists()) {
testOutputsBuilder.add(Pair.of("test.xml", resolvedPaths.getXmlOutputPath()));
}
executor.getEventBus().post(new TestAttempt(action, attempt, data.getTestPassed(), data.getRunDurationMillis(), testOutputsBuilder.build(), true));
finalizeTest(actionExecutionContext, action, dataBuilder.build());
} catch (IOException e) {
executor.getEventHandler().handle(Event.error("Caught I/O exception: " + e));
throw new EnvironmentalExecException("unexpected I/O exception", e);
}
}
use of com.google.devtools.build.lib.vfs.Path in project bazel by bazelbuild.
the class StandaloneTestStrategy method processFailedTestAttempt.
private void processFailedTestAttempt(int attempt, Executor executor, TestRunnerAction action, Builder dataBuilder, TestResultData data, FileOutErr outErr) throws IOException {
ImmutableList.Builder<Pair<String, Path>> testOutputsBuilder = new ImmutableList.Builder<>();
// Rename outputs
String namePrefix = FileSystemUtils.removeExtension(action.getTestLog().getExecPath().getBaseName());
Path attemptsDir = action.getTestLog().getPath().getParentDirectory().getChild(namePrefix + "_attempts");
attemptsDir.createDirectory();
String attemptPrefix = "attempt_" + attempt;
Path testLog = attemptsDir.getChild(attemptPrefix + ".log");
if (action.getTestLog().getPath().exists()) {
action.getTestLog().getPath().renameTo(testLog);
testOutputsBuilder.add(Pair.of("test.log", testLog));
}
ResolvedPaths resolvedPaths = action.resolve(executor.getExecRoot());
if (resolvedPaths.getXmlOutputPath().exists()) {
Path destinationPath = attemptsDir.getChild(attemptPrefix + ".xml");
resolvedPaths.getXmlOutputPath().renameTo(destinationPath);
testOutputsBuilder.add(Pair.of("test.xml", destinationPath));
}
// Add the test log to the output
dataBuilder.addFailedLogs(testLog.toString());
dataBuilder.addTestTimes(data.getTestTimes(0));
dataBuilder.addAllTestProcessTimes(data.getTestProcessTimesList());
executor.getEventBus().post(new TestAttempt(action, attempt, data.getTestPassed(), data.getRunDurationMillis(), testOutputsBuilder.build(), false));
processTestOutput(executor, outErr, new TestResult(action, data, false), testLog);
}
use of com.google.devtools.build.lib.vfs.Path in project bazel by bazelbuild.
the class StandaloneTestStrategy method processTestOutput.
/**
* Outputs test result to the stdout after test has finished (e.g. for --test_output=all or
* --test_output=errors). Will also try to group output lines together (up to 10000 lines) so
* parallel test outputs will not get interleaved.
*/
protected void processTestOutput(Executor executor, FileOutErr outErr, TestResult result, Path testLogPath) throws IOException {
Path testOutput = executor.getExecRoot().getRelative(testLogPath.asFragment());
boolean isPassed = result.getData().getTestPassed();
try {
if (TestLogHelper.shouldOutputTestLog(executionOptions.testOutput, isPassed)) {
TestLogHelper.writeTestLog(testOutput, result.getTestName(), outErr.getOutputStream());
}
} finally {
if (isPassed) {
executor.getEventHandler().handle(Event.of(EventKind.PASS, null, result.getTestName()));
} else {
if (result.getData().getStatus() == BlazeTestStatus.TIMEOUT) {
executor.getEventHandler().handle(Event.of(EventKind.TIMEOUT, null, result.getTestName() + " (see " + testOutput + ")"));
} else {
executor.getEventHandler().handle(Event.of(EventKind.FAIL, null, result.getTestName() + " (see " + testOutput + ")"));
}
}
}
}
Aggregations