use of com.facebook.buck.android.AndroidBuckConfig in project buck by facebook.
the class KnownBuildRuleTypes method createBuilder.
@VisibleForTesting
static Builder createBuilder(BuckConfig config, ProjectFilesystem filesystem, ProcessExecutor processExecutor, AndroidDirectoryResolver androidDirectoryResolver) throws InterruptedException, IOException {
Platform platform = Platform.detect();
AndroidBuckConfig androidConfig = new AndroidBuckConfig(config, platform);
Optional<String> ndkVersion = androidConfig.getNdkVersion();
// out which one we will end up using.
if (!ndkVersion.isPresent()) {
ndkVersion = androidDirectoryResolver.getNdkVersion();
}
AppleConfig appleConfig = new AppleConfig(config);
SwiftBuckConfig swiftBuckConfig = new SwiftBuckConfig(config);
final ImmutableList<AppleCxxPlatform> appleCxxPlatforms = buildAppleCxxPlatforms(filesystem, appleConfig.getAppleDeveloperDirectorySupplier(processExecutor), appleConfig.getExtraToolchainPaths(), appleConfig.getExtraPlatformPaths(), config, appleConfig, swiftBuckConfig, processExecutor);
final FlavorDomain<AppleCxxPlatform> platformFlavorsToAppleCxxPlatforms = FlavorDomain.from("Apple C++ Platform", appleCxxPlatforms);
ImmutableMap.Builder<Flavor, SwiftPlatform> swiftPlatforms = ImmutableMap.builder();
for (Flavor flavor : platformFlavorsToAppleCxxPlatforms.getFlavors()) {
Optional<SwiftPlatform> swiftPlatformOptional = platformFlavorsToAppleCxxPlatforms.getValue(flavor).getSwiftPlatform();
if (swiftPlatformOptional.isPresent()) {
swiftPlatforms.put(flavor, swiftPlatformOptional.get());
}
}
CxxBuckConfig cxxBuckConfig = new CxxBuckConfig(config);
// Setup the NDK C/C++ platforms.
Optional<Path> ndkRoot = androidDirectoryResolver.getNdkOrAbsent();
ImmutableMap.Builder<NdkCxxPlatforms.TargetCpuType, NdkCxxPlatform> ndkCxxPlatformsBuilder = ImmutableMap.builder();
if (ndkRoot.isPresent()) {
NdkCxxPlatformCompiler.Type compilerType = androidConfig.getNdkCompiler().orElse(NdkCxxPlatforms.DEFAULT_COMPILER_TYPE);
String gccVersion = androidConfig.getNdkGccVersion().orElse(NdkCxxPlatforms.getDefaultGccVersionForNdk(ndkVersion));
String clangVersion = androidConfig.getNdkClangVersion().orElse(NdkCxxPlatforms.getDefaultClangVersionForNdk(ndkVersion));
String compilerVersion = compilerType == NdkCxxPlatformCompiler.Type.GCC ? gccVersion : clangVersion;
NdkCxxPlatformCompiler compiler = NdkCxxPlatformCompiler.builder().setType(compilerType).setVersion(compilerVersion).setGccVersion(gccVersion).build();
ndkCxxPlatformsBuilder.putAll(NdkCxxPlatforms.getPlatforms(cxxBuckConfig, filesystem, ndkRoot.get(), compiler, androidConfig.getNdkCxxRuntime().orElse(NdkCxxPlatforms.DEFAULT_CXX_RUNTIME), androidConfig.getNdkAppPlatform().orElse(NdkCxxPlatforms.DEFAULT_TARGET_APP_PLATFORM), androidConfig.getNdkCpuAbis().orElse(NdkCxxPlatforms.DEFAULT_CPU_ABIS), platform));
}
ImmutableMap<NdkCxxPlatforms.TargetCpuType, NdkCxxPlatform> ndkCxxPlatforms = ndkCxxPlatformsBuilder.build();
// Create a map of system platforms.
ImmutableMap.Builder<Flavor, CxxPlatform> cxxSystemPlatformsBuilder = ImmutableMap.builder();
// testing our Android NDK support for right now.
for (NdkCxxPlatform ndkCxxPlatform : ndkCxxPlatforms.values()) {
cxxSystemPlatformsBuilder.put(ndkCxxPlatform.getCxxPlatform().getFlavor(), ndkCxxPlatform.getCxxPlatform());
}
for (AppleCxxPlatform appleCxxPlatform : platformFlavorsToAppleCxxPlatforms.getValues()) {
cxxSystemPlatformsBuilder.put(appleCxxPlatform.getCxxPlatform().getFlavor(), appleCxxPlatform.getCxxPlatform());
}
CxxPlatform defaultHostCxxPlatform = DefaultCxxPlatforms.build(platform, filesystem, cxxBuckConfig);
cxxSystemPlatformsBuilder.put(defaultHostCxxPlatform.getFlavor(), defaultHostCxxPlatform);
ImmutableMap<Flavor, CxxPlatform> cxxSystemPlatformsMap = cxxSystemPlatformsBuilder.build();
// Add the host platform if needed (for example, when building on Linux).
Flavor hostFlavor = CxxPlatforms.getHostFlavor();
if (!cxxSystemPlatformsMap.containsKey(hostFlavor)) {
cxxSystemPlatformsBuilder.put(hostFlavor, CxxPlatform.builder().from(defaultHostCxxPlatform).setFlavor(hostFlavor).build());
cxxSystemPlatformsMap = cxxSystemPlatformsBuilder.build();
}
// Add platforms for each cxx flavor obtained from the buck config files
// from sections of the form cxx#{flavor name}.
// These platforms are overrides for existing system platforms.
ImmutableSet<Flavor> possibleHostFlavors = CxxPlatforms.getAllPossibleHostFlavors();
HashMap<Flavor, CxxPlatform> cxxOverridePlatformsMap = new HashMap<Flavor, CxxPlatform>(cxxSystemPlatformsMap);
ImmutableSet<Flavor> cxxFlavors = CxxBuckConfig.getCxxFlavors(config);
for (Flavor flavor : cxxFlavors) {
CxxPlatform baseCxxPlatform = cxxSystemPlatformsMap.get(flavor);
if (baseCxxPlatform == null) {
if (possibleHostFlavors.contains(flavor)) {
// If a flavor is for an alternate host, it's safe to skip.
continue;
}
LOG.info("Applying \"%s\" overrides to default host platform", flavor);
baseCxxPlatform = defaultHostCxxPlatform;
}
cxxOverridePlatformsMap.put(flavor, CxxPlatforms.copyPlatformWithFlavorAndConfig(baseCxxPlatform, platform, new CxxBuckConfig(config, flavor), flavor));
}
// Finalize our "default" host.
// TODO(Ktwu) The host flavor should default to a concrete flavor
// like "linux-x86_64", not "default".
hostFlavor = DefaultCxxPlatforms.FLAVOR;
Optional<String> hostCxxPlatformOverride = cxxBuckConfig.getHostPlatform();
if (hostCxxPlatformOverride.isPresent()) {
Flavor overrideFlavor = InternalFlavor.of(hostCxxPlatformOverride.get());
if (cxxOverridePlatformsMap.containsKey(overrideFlavor)) {
hostFlavor = overrideFlavor;
}
}
CxxPlatform hostCxxPlatform = CxxPlatform.builder().from(cxxOverridePlatformsMap.get(hostFlavor)).setFlavor(DefaultCxxPlatforms.FLAVOR).build();
cxxOverridePlatformsMap.put(DefaultCxxPlatforms.FLAVOR, hostCxxPlatform);
ImmutableMap<Flavor, CxxPlatform> cxxPlatformsMap = ImmutableMap.<Flavor, CxxPlatform>builder().putAll(cxxOverridePlatformsMap).build();
ExecutableFinder executableFinder = new ExecutableFinder();
// Build up the final list of C/C++ platforms.
FlavorDomain<CxxPlatform> cxxPlatforms = new FlavorDomain<>("C/C++ platform", cxxPlatformsMap);
// Get the default target platform from config.
CxxPlatform defaultCxxPlatform = CxxPlatforms.getConfigDefaultCxxPlatform(cxxBuckConfig, cxxPlatformsMap, hostCxxPlatform);
DBuckConfig dBuckConfig = new DBuckConfig(config);
ReactNativeBuckConfig reactNativeBuckConfig = new ReactNativeBuckConfig(config);
RustBuckConfig rustBuckConfig = new RustBuckConfig(config);
GoBuckConfig goBuckConfig = new GoBuckConfig(config, processExecutor, cxxPlatforms);
HalideBuckConfig halideBuckConfig = new HalideBuckConfig(config);
ProGuardConfig proGuardConfig = new ProGuardConfig(config);
DxConfig dxConfig = new DxConfig(config);
PythonBuckConfig pyConfig = new PythonBuckConfig(config, executableFinder);
ImmutableList<PythonPlatform> pythonPlatformsList = pyConfig.getPythonPlatforms(processExecutor);
FlavorDomain<PythonPlatform> pythonPlatforms = FlavorDomain.from("Python Platform", pythonPlatformsList);
PythonBinaryDescription pythonBinaryDescription = new PythonBinaryDescription(pyConfig, pythonPlatforms, cxxBuckConfig, defaultCxxPlatform, cxxPlatforms);
// Look up the timeout to apply to entire test rules.
Optional<Long> defaultTestRuleTimeoutMs = config.getLong("test", "rule_timeout");
// Prepare the downloader if we're allowing mid-build downloads
Downloader downloader;
DownloadConfig downloadConfig = new DownloadConfig(config);
if (downloadConfig.isDownloadAtRuntimeOk()) {
downloader = StackedDownloader.createFromConfig(config, androidDirectoryResolver.getSdkOrAbsent());
} else {
// Or just set one that blows up
downloader = new ExplodingDownloader();
}
Builder builder = builder();
JavaBuckConfig javaConfig = config.getView(JavaBuckConfig.class);
JavacOptions defaultJavacOptions = javaConfig.getDefaultJavacOptions();
JavaOptions defaultJavaOptions = javaConfig.getDefaultJavaOptions();
JavaOptions defaultJavaOptionsForTests = javaConfig.getDefaultJavaOptionsForTests();
KotlinBuckConfig kotlinBuckConfig = new KotlinBuckConfig(config);
ScalaBuckConfig scalaConfig = new ScalaBuckConfig(config);
InferBuckConfig inferBuckConfig = new InferBuckConfig(config);
LuaConfig luaConfig = new LuaBuckConfig(config, executableFinder);
CxxBinaryDescription cxxBinaryDescription = new CxxBinaryDescription(cxxBuckConfig, inferBuckConfig, defaultCxxPlatform, cxxPlatforms);
CxxLibraryDescription cxxLibraryDescription = new CxxLibraryDescription(cxxBuckConfig, defaultCxxPlatform, inferBuckConfig, cxxPlatforms);
FlavorDomain<SwiftPlatform> platformFlavorsToSwiftPlatforms = new FlavorDomain<>("Swift Platform", swiftPlatforms.build());
SwiftLibraryDescription swiftLibraryDescription = new SwiftLibraryDescription(cxxBuckConfig, swiftBuckConfig, cxxPlatforms, platformFlavorsToSwiftPlatforms);
builder.register(swiftLibraryDescription);
CodeSignIdentityStore codeSignIdentityStore = CodeSignIdentityStore.fromSystem(processExecutor, appleConfig.getCodeSignIdentitiesCommand());
ProvisioningProfileStore provisioningProfileStore = ProvisioningProfileStore.fromSearchPath(processExecutor, appleConfig.getProvisioningProfileReadCommand(), appleConfig.getProvisioningProfileSearchPath());
AppleLibraryDescription appleLibraryDescription = new AppleLibraryDescription(cxxLibraryDescription, swiftLibraryDescription, platformFlavorsToAppleCxxPlatforms, defaultCxxPlatform, codeSignIdentityStore, provisioningProfileStore, appleConfig);
builder.register(appleLibraryDescription);
PrebuiltAppleFrameworkDescription appleFrameworkDescription = new PrebuiltAppleFrameworkDescription();
builder.register(appleFrameworkDescription);
AppleBinaryDescription appleBinaryDescription = new AppleBinaryDescription(cxxBinaryDescription, swiftLibraryDescription, platformFlavorsToAppleCxxPlatforms, codeSignIdentityStore, provisioningProfileStore, appleConfig);
builder.register(appleBinaryDescription);
HaskellBuckConfig haskellBuckConfig = new HaskellBuckConfig(config, executableFinder);
builder.register(new HaskellLibraryDescription(haskellBuckConfig, cxxBuckConfig, cxxPlatforms));
builder.register(new HaskellBinaryDescription(haskellBuckConfig, cxxPlatforms, defaultCxxPlatform));
builder.register(new HaskellPrebuiltLibraryDescription());
if (javaConfig.getDxThreadCount().isPresent()) {
LOG.warn("java.dx_threads has been deprecated. Use dx.max_threads instead");
}
// Create an executor service exclusively for the smart dexing step.
ListeningExecutorService dxExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(dxConfig.getDxMaxThreadCount().orElse(javaConfig.getDxThreadCount().orElse(SmartDexingStep.determineOptimalThreadCount())), new CommandThreadFactory("SmartDexing")));
builder.register(new AndroidAarDescription(new AndroidManifestDescription(), cxxBuckConfig, defaultJavacOptions, ndkCxxPlatforms));
builder.register(new AndroidBinaryDescription(defaultJavaOptions, defaultJavacOptions, proGuardConfig, ndkCxxPlatforms, dxExecutorService, config, cxxBuckConfig, dxConfig));
builder.register(new AndroidBuildConfigDescription(defaultJavacOptions));
builder.register(new AndroidInstrumentationApkDescription(proGuardConfig, defaultJavacOptions, ndkCxxPlatforms, dxExecutorService, cxxBuckConfig, dxConfig));
builder.register(new AndroidInstrumentationTestDescription(defaultJavaOptions, defaultTestRuleTimeoutMs));
builder.register(new AndroidLibraryDescription(defaultJavacOptions, new DefaultAndroidLibraryCompilerFactory(scalaConfig, kotlinBuckConfig)));
builder.register(new AndroidManifestDescription());
builder.register(new AndroidPrebuiltAarDescription(defaultJavacOptions));
builder.register(new AndroidReactNativeLibraryDescription(reactNativeBuckConfig));
builder.register(new AndroidResourceDescription(config.isGrayscaleImageProcessingEnabled()));
builder.register(new ApkGenruleDescription());
builder.register(new AppleAssetCatalogDescription());
builder.register(new ApplePackageDescription(appleConfig, defaultCxxPlatform, platformFlavorsToAppleCxxPlatforms));
AppleBundleDescription appleBundleDescription = new AppleBundleDescription(appleBinaryDescription, appleLibraryDescription, cxxPlatforms, platformFlavorsToAppleCxxPlatforms, defaultCxxPlatform, codeSignIdentityStore, provisioningProfileStore, appleConfig);
builder.register(appleBundleDescription);
builder.register(new AppleResourceDescription());
builder.register(new AppleTestDescription(appleConfig, appleLibraryDescription, cxxPlatforms, platformFlavorsToAppleCxxPlatforms, defaultCxxPlatform, codeSignIdentityStore, provisioningProfileStore, appleConfig.getAppleDeveloperDirectorySupplierForTests(processExecutor), defaultTestRuleTimeoutMs));
builder.register(new CoreDataModelDescription());
builder.register(new CsharpLibraryDescription());
builder.register(cxxBinaryDescription);
builder.register(cxxLibraryDescription);
builder.register(new CxxGenruleDescription(cxxPlatforms));
builder.register(new CxxLuaExtensionDescription(luaConfig, cxxBuckConfig, cxxPlatforms));
builder.register(new CxxPythonExtensionDescription(pythonPlatforms, cxxBuckConfig, cxxPlatforms));
builder.register(new CxxTestDescription(cxxBuckConfig, defaultCxxPlatform, cxxPlatforms, defaultTestRuleTimeoutMs));
builder.register(new DBinaryDescription(dBuckConfig, cxxBuckConfig, defaultCxxPlatform));
builder.register(new DLibraryDescription(dBuckConfig, cxxBuckConfig, defaultCxxPlatform));
builder.register(new DTestDescription(dBuckConfig, cxxBuckConfig, defaultCxxPlatform, defaultTestRuleTimeoutMs));
builder.register(new ExportFileDescription());
builder.register(new GenruleDescription());
builder.register(new GenAidlDescription());
builder.register(new GoBinaryDescription(goBuckConfig));
builder.register(new GoLibraryDescription(goBuckConfig));
builder.register(new GoTestDescription(goBuckConfig, defaultTestRuleTimeoutMs));
builder.register(new GraphqlLibraryDescription());
GroovyBuckConfig groovyBuckConfig = new GroovyBuckConfig(config);
builder.register(new GroovyLibraryDescription(groovyBuckConfig, defaultJavacOptions));
builder.register(new GroovyTestDescription(groovyBuckConfig, defaultJavaOptionsForTests, defaultJavacOptions, defaultTestRuleTimeoutMs));
builder.register(new GwtBinaryDescription(defaultJavaOptions));
builder.register(new HalideLibraryDescription(cxxBuckConfig, defaultCxxPlatform, cxxPlatforms, halideBuckConfig));
builder.register(new IosReactNativeLibraryDescription(reactNativeBuckConfig));
builder.register(new JavaBinaryDescription(defaultJavaOptions, defaultJavacOptions, defaultCxxPlatform, javaConfig));
builder.register(new JavaAnnotationProcessorDescription());
builder.register(new JavaLibraryDescription(defaultJavacOptions));
builder.register(new JavaTestDescription(defaultJavaOptionsForTests, defaultJavacOptions, defaultTestRuleTimeoutMs, defaultCxxPlatform));
builder.register(new JsBundleDescription());
builder.register(new JsLibraryDescription());
builder.register(new KeystoreDescription());
builder.register(new KotlinLibraryDescription(kotlinBuckConfig, defaultJavacOptions));
builder.register(new KotlinTestDescription(kotlinBuckConfig, defaultJavaOptionsForTests, defaultJavacOptions, defaultTestRuleTimeoutMs));
builder.register(new LuaBinaryDescription(luaConfig, cxxBuckConfig, defaultCxxPlatform, cxxPlatforms, pythonPlatforms));
builder.register(new LuaLibraryDescription());
builder.register(new NdkLibraryDescription(ndkVersion, ndkCxxPlatforms));
OcamlBuckConfig ocamlBuckConfig = new OcamlBuckConfig(config, defaultCxxPlatform);
builder.register(new OcamlBinaryDescription(ocamlBuckConfig));
builder.register(new OcamlLibraryDescription(ocamlBuckConfig));
builder.register(new PrebuiltCxxLibraryDescription(cxxBuckConfig, cxxPlatforms));
builder.register(PrebuiltCxxLibraryGroupDescription.of());
builder.register(new CxxPrecompiledHeaderDescription());
builder.register(new PrebuiltDotnetLibraryDescription());
builder.register(new PrebuiltJarDescription());
builder.register(new PrebuiltNativeLibraryDescription());
builder.register(new PrebuiltOcamlLibraryDescription());
builder.register(new PrebuiltPythonLibraryDescription());
builder.register(new ProjectConfigDescription());
builder.register(pythonBinaryDescription);
PythonLibraryDescription pythonLibraryDescription = new PythonLibraryDescription(pythonPlatforms, cxxPlatforms);
builder.register(pythonLibraryDescription);
builder.register(new PythonTestDescription(pythonBinaryDescription, pyConfig, pythonPlatforms, cxxBuckConfig, defaultCxxPlatform, defaultTestRuleTimeoutMs, cxxPlatforms));
builder.register(new RemoteFileDescription(downloader));
builder.register(new RobolectricTestDescription(defaultJavaOptionsForTests, defaultJavacOptions, defaultTestRuleTimeoutMs, defaultCxxPlatform));
builder.register(new RustBinaryDescription(rustBuckConfig, cxxPlatforms, defaultCxxPlatform));
builder.register(new RustLibraryDescription(rustBuckConfig, cxxPlatforms, defaultCxxPlatform));
builder.register(new RustTestDescription(rustBuckConfig, cxxPlatforms, defaultCxxPlatform));
builder.register(new PrebuiltRustLibraryDescription());
builder.register(new ScalaLibraryDescription(scalaConfig));
builder.register(new ScalaTestDescription(scalaConfig, defaultJavaOptionsForTests, defaultTestRuleTimeoutMs, defaultCxxPlatform));
builder.register(new SceneKitAssetsDescription());
builder.register(new ShBinaryDescription());
builder.register(new ShTestDescription(defaultTestRuleTimeoutMs));
builder.register(new WorkerToolDescription(config));
builder.register(new XcodePostbuildScriptDescription());
builder.register(new XcodePrebuildScriptDescription());
builder.register(new XcodeWorkspaceConfigDescription());
builder.register(new ZipFileDescription());
builder.register(new TargetGroupDescription());
builder.setCxxPlatforms(cxxPlatforms);
builder.setDefaultCxxPlatform(defaultCxxPlatform);
builder.register(VersionedAliasDescription.of());
return builder;
}
use of com.facebook.buck.android.AndroidBuckConfig in project buck by facebook.
the class Main method runMainWithExitCode.
/**
* @param buildId an identifier for this command execution.
* @param context an optional NGContext that is present if running inside a Nailgun server.
* @param initTimestamp Value of System.nanoTime() when process got main()/nailMain() invoked.
* @param unexpandedCommandLineArgs command line arguments
* @return an exit code or {@code null} if this is a process that should not exit
*/
@SuppressWarnings("PMD.PrematureDeclaration")
public int runMainWithExitCode(BuildId buildId, Path projectRoot, Optional<NGContext> context, ImmutableMap<String, String> clientEnvironment, CommandMode commandMode, WatchmanWatcher.FreshInstanceAction watchmanFreshInstanceAction, final long initTimestamp, String... unexpandedCommandLineArgs) throws IOException, InterruptedException {
String[] args = BuckArgsMethods.expandAtFiles(unexpandedCommandLineArgs);
// Parse the command line args.
BuckCommand command = new BuckCommand();
AdditionalOptionsCmdLineParser cmdLineParser = new AdditionalOptionsCmdLineParser(command);
try {
cmdLineParser.parseArgument(args);
} catch (CmdLineException e) {
// Can't go through the console for prettification since that needs the BuckConfig, and that
// needs to be created with the overrides, which are parsed from the command line here, which
// required the console to print the message that parsing has failed. So just write to stderr
// and be done with it.
stdErr.println(e.getLocalizedMessage());
stdErr.println("For help see 'buck --help'.");
return 1;
}
{
// Return help strings fast if the command is a help request.
OptionalInt result = command.runHelp(stdErr);
if (result.isPresent()) {
return result.getAsInt();
}
}
// Setup logging.
if (commandMode.isLoggingEnabled()) {
// Reset logging each time we run a command while daemonized.
// This will cause us to write a new log per command.
LOG.debug("Rotating log.");
LogConfig.flushLogs();
LogConfig.setupLogging(command.getLogConfig());
if (LOG.isDebugEnabled()) {
Long gitCommitTimestamp = Long.getLong("buck.git_commit_timestamp");
String buildDateStr;
if (gitCommitTimestamp == null) {
buildDateStr = "(unknown)";
} else {
buildDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US).format(new Date(TimeUnit.SECONDS.toMillis(gitCommitTimestamp)));
}
String buildRev = System.getProperty("buck.git_commit", "(unknown)");
LOG.debug("Starting up (build date %s, rev %s), args: %s", buildDateStr, buildRev, Arrays.toString(args));
LOG.debug("System properties: %s", System.getProperties());
}
}
// Setup filesystem and buck config.
Path canonicalRootPath = projectRoot.toRealPath().normalize();
Config config = Configs.createDefaultConfig(canonicalRootPath, command.getConfigOverrides().getForCell(RelativeCellName.ROOT_CELL_NAME));
ProjectFilesystem filesystem = new ProjectFilesystem(canonicalRootPath, config);
DefaultCellPathResolver cellPathResolver = new DefaultCellPathResolver(filesystem.getRootPath(), config);
BuckConfig buckConfig = new BuckConfig(config, filesystem, architecture, platform, clientEnvironment, cellPathResolver);
ImmutableSet<Path> projectWatchList = ImmutableSet.<Path>builder().add(canonicalRootPath).addAll(buckConfig.getView(ParserConfig.class).getWatchCells() ? cellPathResolver.getTransitivePathMapping().values() : ImmutableList.of()).build();
Optional<ImmutableList<String>> allowedJavaSpecificiationVersions = buckConfig.getAllowedJavaSpecificationVersions();
if (allowedJavaSpecificiationVersions.isPresent()) {
String specificationVersion = System.getProperty("java.specification.version");
boolean javaSpecificationVersionIsAllowed = allowedJavaSpecificiationVersions.get().contains(specificationVersion);
if (!javaSpecificationVersionIsAllowed) {
throw new HumanReadableException("Current Java version '%s' is not in the allowed java specification versions:\n%s", specificationVersion, Joiner.on(", ").join(allowedJavaSpecificiationVersions.get()));
}
}
// Setup the console.
Verbosity verbosity = VerbosityParser.parse(args);
Optional<String> color;
if (context.isPresent() && (context.get().getEnv() != null)) {
String colorString = context.get().getEnv().getProperty(BUCKD_COLOR_DEFAULT_ENV_VAR);
color = Optional.ofNullable(colorString);
} else {
color = Optional.empty();
}
final Console console = new Console(verbosity, stdOut, stdErr, buckConfig.createAnsi(color));
// No more early outs: if this command is not read only, acquire the command semaphore to
// become the only executing read/write command.
// This must happen immediately before the try block to ensure that the semaphore is released.
boolean commandSemaphoreAcquired = false;
boolean shouldCleanUpTrash = false;
if (!command.isReadOnly()) {
commandSemaphoreAcquired = commandSemaphore.tryAcquire();
if (!commandSemaphoreAcquired) {
LOG.warn("Buck server was busy executing a command. Maybe retrying later will help.");
return BUSY_EXIT_CODE;
}
}
try {
if (commandSemaphoreAcquired) {
commandSemaphoreNgClient = context;
}
if (!command.isReadOnly()) {
Optional<String> currentVersion = filesystem.readFileIfItExists(filesystem.getBuckPaths().getCurrentVersionFile());
BuckPaths unconfiguredPaths = filesystem.getBuckPaths().withConfiguredBuckOut(filesystem.getBuckPaths().getBuckOut());
if (!currentVersion.isPresent() || !currentVersion.get().equals(BuckVersion.getVersion()) || (filesystem.exists(unconfiguredPaths.getGenDir(), LinkOption.NOFOLLOW_LINKS) && (filesystem.isSymLink(unconfiguredPaths.getGenDir()) ^ buckConfig.getBuckOutCompatLink()))) {
// Migrate any version-dependent directories (which might be huge) to a trash directory
// so we can delete it asynchronously after the command is done.
moveToTrash(filesystem, console, buildId, filesystem.getBuckPaths().getAnnotationDir(), filesystem.getBuckPaths().getGenDir(), filesystem.getBuckPaths().getScratchDir(), filesystem.getBuckPaths().getResDir());
shouldCleanUpTrash = true;
filesystem.mkdirs(filesystem.getBuckPaths().getCurrentVersionFile().getParent());
filesystem.writeContentsToPath(BuckVersion.getVersion(), filesystem.getBuckPaths().getCurrentVersionFile());
}
}
AndroidBuckConfig androidBuckConfig = new AndroidBuckConfig(buckConfig, platform);
AndroidDirectoryResolver androidDirectoryResolver = new DefaultAndroidDirectoryResolver(filesystem.getRootPath().getFileSystem(), clientEnvironment, androidBuckConfig.getBuildToolsVersion(), androidBuckConfig.getNdkVersion());
ProcessExecutor processExecutor = new DefaultProcessExecutor(console);
Clock clock;
boolean enableThreadCpuTime = buckConfig.getBooleanValue("build", "enable_thread_cpu_time", true);
if (BUCKD_LAUNCH_TIME_NANOS.isPresent()) {
long nanosEpoch = Long.parseLong(BUCKD_LAUNCH_TIME_NANOS.get(), 10);
LOG.verbose("Using nanos epoch: %d", nanosEpoch);
clock = new NanosAdjustedClock(nanosEpoch, enableThreadCpuTime);
} else {
clock = new DefaultClock(enableThreadCpuTime);
}
ParserConfig parserConfig = buckConfig.getView(ParserConfig.class);
try (Watchman watchman = buildWatchman(context, parserConfig, projectWatchList, clientEnvironment, console, clock)) {
final boolean isDaemon = context.isPresent() && (watchman != Watchman.NULL_WATCHMAN);
if (!isDaemon && shouldCleanUpTrash) {
// Clean up the trash on a background thread if this was a
// non-buckd read-write command. (We don't bother waiting
// for it to complete; the thread is a daemon thread which
// will just be terminated at shutdown time.)
TRASH_CLEANER.startCleaningDirectory(filesystem.getBuckPaths().getTrashDir());
}
KnownBuildRuleTypesFactory factory = new KnownBuildRuleTypesFactory(processExecutor, androidDirectoryResolver);
Cell rootCell = CellProvider.createForLocalBuild(filesystem, watchman, buckConfig, command.getConfigOverrides(), factory).getCellByPath(filesystem.getRootPath());
int exitCode;
ImmutableList<BuckEventListener> eventListeners = ImmutableList.of();
ExecutionEnvironment executionEnvironment = new DefaultExecutionEnvironment(clientEnvironment, System.getProperties());
ImmutableList.Builder<ProjectFileHashCache> allCaches = ImmutableList.builder();
// Build up the hash cache, which is a collection of the stateful cell cache and some
// per-run caches.
//
// TODO(Coneko, ruibm, andrewjcg): Determine whether we can use the existing filesystem
// object that is in scope instead of creating a new rootCellProjectFilesystem. The primary
// difference appears to be that filesystem is created with a Config that is used to produce
// ImmutableSet<PathOrGlobMatcher> and BuckPaths for the ProjectFilesystem, whereas this one
// uses the defaults.
ProjectFilesystem rootCellProjectFilesystem = ProjectFilesystem.createNewOrThrowHumanReadableException(rootCell.getFilesystem().getRootPath());
if (isDaemon) {
allCaches.addAll(getFileHashCachesFromDaemon(rootCell));
} else {
getTransitiveCells(rootCell).stream().map(cell -> DefaultFileHashCache.createDefaultFileHashCache(cell.getFilesystem())).forEach(allCaches::add);
allCaches.add(DefaultFileHashCache.createBuckOutFileHashCache(rootCellProjectFilesystem, rootCell.getFilesystem().getBuckPaths().getBuckOut()));
}
// A cache which caches hashes of cell-relative paths which may have been ignore by
// the main cell cache, and only serves to prevent rehashing the same file multiple
// times in a single run.
allCaches.add(DefaultFileHashCache.createDefaultFileHashCache(rootCellProjectFilesystem));
allCaches.addAll(DefaultFileHashCache.createOsRootDirectoriesCaches());
StackedFileHashCache fileHashCache = new StackedFileHashCache(allCaches.build());
Optional<WebServer> webServer = getWebServerIfDaemon(context, rootCell);
Optional<ConcurrentMap<String, WorkerProcessPool>> persistentWorkerPools = getPersistentWorkerPoolsIfDaemon(context, rootCell);
TestConfig testConfig = new TestConfig(buckConfig);
ArtifactCacheBuckConfig cacheBuckConfig = new ArtifactCacheBuckConfig(buckConfig);
ExecutorService diskIoExecutorService = MostExecutors.newSingleThreadExecutor("Disk I/O");
ListeningExecutorService httpWriteExecutorService = getHttpWriteExecutorService(cacheBuckConfig);
ScheduledExecutorService counterAggregatorExecutor = Executors.newSingleThreadScheduledExecutor(new CommandThreadFactory("CounterAggregatorThread"));
VersionControlStatsGenerator vcStatsGenerator;
// Eventually, we'll want to get allow websocket and/or nailgun clients to specify locale
// when connecting. For now, we'll use the default from the server environment.
Locale locale = Locale.getDefault();
// Create a cached thread pool for cpu intensive tasks
Map<ExecutorPool, ListeningExecutorService> executors = new HashMap<>();
executors.put(ExecutorPool.CPU, listeningDecorator(Executors.newCachedThreadPool()));
// Create a thread pool for network I/O tasks
executors.put(ExecutorPool.NETWORK, newDirectExecutorService());
executors.put(ExecutorPool.PROJECT, listeningDecorator(MostExecutors.newMultiThreadExecutor("Project", buckConfig.getNumThreads())));
// Create and register the event buses that should listen to broadcast events.
// If the build doesn't have a daemon create a new instance.
BroadcastEventListener broadcastEventListener = getBroadcastEventListener(isDaemon, rootCell, objectMapper);
// The order of resources in the try-with-resources block is important: the BuckEventBus
// must be the last resource, so that it is closed first and can deliver its queued events
// to the other resources before they are closed.
InvocationInfo invocationInfo = InvocationInfo.of(buildId, isSuperConsoleEnabled(console), isDaemon, command.getSubCommandNameForLogging(), filesystem.getBuckPaths().getLogDir());
try (GlobalStateManager.LoggerIsMappedToThreadScope loggerThreadMappingScope = GlobalStateManager.singleton().setupLoggers(invocationInfo, console.getStdErr(), stdErr, verbosity);
AbstractConsoleEventBusListener consoleListener = createConsoleEventListener(clock, new SuperConsoleConfig(buckConfig), console, testConfig.getResultSummaryVerbosity(), executionEnvironment, webServer, locale, filesystem.getBuckPaths().getLogDir().resolve("test.log"));
AsyncCloseable asyncCloseable = new AsyncCloseable(diskIoExecutorService);
BuckEventBus buildEventBus = new BuckEventBus(clock, buildId);
BroadcastEventListener.BroadcastEventBusClosable broadcastEventBusClosable = broadcastEventListener.addEventBus(buildEventBus);
// stderr.
Closeable logErrorToEventBus = loggerThreadMappingScope.setWriter(createWriterForConsole(consoleListener));
// NOTE: This will only run during the lifetime of the process and will flush on close.
CounterRegistry counterRegistry = new CounterRegistryImpl(counterAggregatorExecutor, buildEventBus, buckConfig.getCountersFirstFlushIntervalMillis(), buckConfig.getCountersFlushIntervalMillis());
PerfStatsTracking perfStatsTracking = new PerfStatsTracking(buildEventBus, invocationInfo);
ProcessTracker processTracker = buckConfig.isProcessTrackerEnabled() && platform != Platform.WINDOWS ? new ProcessTracker(buildEventBus, invocationInfo, isDaemon, buckConfig.isProcessTrackerDeepEnabled()) : null) {
LOG.debug(invocationInfo.toLogLine(args));
buildEventBus.register(HANG_MONITOR.getHangMonitor());
ArtifactCaches artifactCacheFactory = new ArtifactCaches(cacheBuckConfig, buildEventBus, filesystem, executionEnvironment.getWifiSsid(), httpWriteExecutorService, Optional.of(asyncCloseable));
ProgressEstimator progressEstimator = new ProgressEstimator(filesystem.resolve(filesystem.getBuckPaths().getBuckOut()).resolve(ProgressEstimator.PROGRESS_ESTIMATIONS_JSON), buildEventBus, objectMapper);
consoleListener.setProgressEstimator(progressEstimator);
BuildEnvironmentDescription buildEnvironmentDescription = getBuildEnvironmentDescription(executionEnvironment, buckConfig);
Iterable<BuckEventListener> commandEventListeners = command.getSubcommand().isPresent() ? command.getSubcommand().get().getEventListeners(invocationInfo.getLogDirectoryPath(), filesystem) : ImmutableList.of();
Supplier<BuckEventListener> missingSymbolsListenerSupplier = () -> {
return MissingSymbolsHandler.createListener(rootCell.getFilesystem(), rootCell.getKnownBuildRuleTypes().getAllDescriptions(), rootCell.getBuckConfig(), buildEventBus, console, buckConfig.getView(JavaBuckConfig.class).getDefaultJavacOptions(), clientEnvironment);
};
eventListeners = addEventListeners(buildEventBus, rootCell.getFilesystem(), invocationInfo, rootCell.getBuckConfig(), webServer, clock, consoleListener, missingSymbolsListenerSupplier, counterRegistry, commandEventListeners);
if (commandMode == CommandMode.RELEASE && buckConfig.isPublicAnnouncementsEnabled()) {
PublicAnnouncementManager announcementManager = new PublicAnnouncementManager(clock, buildEventBus, consoleListener, buckConfig.getRepository().orElse("unknown"), new RemoteLogBuckConfig(buckConfig), executors.get(ExecutorPool.CPU));
announcementManager.getAndPostAnnouncements();
}
// This needs to be after the registration of the event listener so they can pick it up.
if (watchmanFreshInstanceAction == WatchmanWatcher.FreshInstanceAction.NONE) {
buildEventBus.post(DaemonEvent.newDaemonInstance());
}
if (command.subcommand instanceof AbstractCommand) {
AbstractCommand subcommand = (AbstractCommand) command.subcommand;
VersionControlBuckConfig vcBuckConfig = new VersionControlBuckConfig(buckConfig);
if (!commandMode.equals(CommandMode.TEST) && (subcommand.isSourceControlStatsGatheringEnabled() || vcBuckConfig.shouldGenerateStatistics())) {
vcStatsGenerator = new VersionControlStatsGenerator(diskIoExecutorService, new DefaultVersionControlCmdLineInterfaceFactory(rootCell.getFilesystem().getRootPath(), new PrintStreamProcessExecutorFactory(), vcBuckConfig, buckConfig.getEnvironment()), buildEventBus);
vcStatsGenerator.generateStatsAsync();
}
}
ImmutableList<String> remainingArgs = args.length > 1 ? ImmutableList.copyOf(Arrays.copyOfRange(args, 1, args.length)) : ImmutableList.of();
CommandEvent.Started startedEvent = CommandEvent.started(args.length > 0 ? args[0] : "", remainingArgs, isDaemon, getBuckPID());
buildEventBus.post(startedEvent);
// Create or get Parser and invalidate cached command parameters.
Parser parser = null;
VersionedTargetGraphCache versionedTargetGraphCache = null;
ActionGraphCache actionGraphCache = null;
Optional<RuleKeyCacheRecycler<RuleKey>> defaultRuleKeyFactoryCacheRecycler = Optional.empty();
if (isDaemon) {
try {
Daemon daemon = getDaemon(rootCell, objectMapper);
WatchmanWatcher watchmanWatcher = createWatchmanWatcher(daemon, watchman.getProjectWatches(), daemon.getFileEventBus(), ImmutableSet.<PathOrGlobMatcher>builder().addAll(filesystem.getIgnorePaths()).addAll(DEFAULT_IGNORE_GLOBS).build(), watchman);
parser = getParserFromDaemon(context, rootCell, startedEvent, buildEventBus, watchmanWatcher, watchmanFreshInstanceAction);
versionedTargetGraphCache = daemon.getVersionedTargetGraphCache();
actionGraphCache = daemon.getActionGraphCache();
if (buckConfig.getRuleKeyCaching()) {
LOG.debug("Using rule key calculation caching");
defaultRuleKeyFactoryCacheRecycler = Optional.of(daemon.getDefaultRuleKeyFactoryCacheRecycler());
}
} catch (WatchmanWatcherException | IOException e) {
buildEventBus.post(ConsoleEvent.warning("Watchman threw an exception while parsing file changes.\n%s", e.getMessage()));
}
}
if (versionedTargetGraphCache == null) {
versionedTargetGraphCache = new VersionedTargetGraphCache();
}
if (actionGraphCache == null) {
actionGraphCache = new ActionGraphCache(broadcastEventListener);
}
if (parser == null) {
TypeCoercerFactory typeCoercerFactory = new DefaultTypeCoercerFactory(objectMapper);
parser = new Parser(broadcastEventListener, rootCell.getBuckConfig().getView(ParserConfig.class), typeCoercerFactory, new ConstructorArgMarshaller(typeCoercerFactory));
}
// Because the Parser is potentially constructed before the CounterRegistry,
// we need to manually register its counters after it's created.
//
// The counters will be unregistered once the counter registry is closed.
counterRegistry.registerCounters(parser.getCounters());
JavaUtilsLoggingBuildListener.ensureLogFileIsWritten(rootCell.getFilesystem());
Optional<ProcessManager> processManager;
if (platform == Platform.WINDOWS) {
processManager = Optional.empty();
} else {
processManager = Optional.of(new PkillProcessManager(processExecutor));
}
Supplier<AndroidPlatformTarget> androidPlatformTargetSupplier = createAndroidPlatformTargetSupplier(androidDirectoryResolver, androidBuckConfig, buildEventBus);
// event-listener.
if (command.subcommand instanceof AbstractCommand) {
AbstractCommand subcommand = (AbstractCommand) command.subcommand;
Optional<Path> eventsOutputPath = subcommand.getEventsOutputPath();
if (eventsOutputPath.isPresent()) {
BuckEventListener listener = new FileSerializationEventBusListener(eventsOutputPath.get(), objectMapper);
buildEventBus.register(listener);
}
}
buildEventBus.post(new BuckInitializationDurationEvent(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - initTimestamp)));
try {
exitCode = command.run(CommandRunnerParams.builder().setConsole(console).setStdIn(stdIn).setCell(rootCell).setAndroidPlatformTargetSupplier(androidPlatformTargetSupplier).setArtifactCacheFactory(artifactCacheFactory).setBuckEventBus(buildEventBus).setParser(parser).setPlatform(platform).setEnvironment(clientEnvironment).setJavaPackageFinder(rootCell.getBuckConfig().getView(JavaBuckConfig.class).createDefaultJavaPackageFinder()).setObjectMapper(objectMapper).setClock(clock).setProcessManager(processManager).setPersistentWorkerPools(persistentWorkerPools).setWebServer(webServer).setBuckConfig(buckConfig).setFileHashCache(fileHashCache).setExecutors(executors).setBuildEnvironmentDescription(buildEnvironmentDescription).setVersionedTargetGraphCache(versionedTargetGraphCache).setActionGraphCache(actionGraphCache).setKnownBuildRuleTypesFactory(factory).setInvocationInfo(Optional.of(invocationInfo)).setDefaultRuleKeyFactoryCacheRecycler(defaultRuleKeyFactoryCacheRecycler).build());
} catch (InterruptedException | ClosedByInterruptException e) {
exitCode = INTERRUPTED_EXIT_CODE;
buildEventBus.post(CommandEvent.interrupted(startedEvent, INTERRUPTED_EXIT_CODE));
throw e;
}
// Let's avoid an infinite loop
if (exitCode == BUSY_EXIT_CODE) {
// Some loss of info here, but better than looping
exitCode = FAIL_EXIT_CODE;
LOG.error("Buck return with exit code %d which we use to indicate busy status. " + "This is probably propagating an exit code from a sub process or tool. " + "Coercing to %d to avoid retries.", BUSY_EXIT_CODE, FAIL_EXIT_CODE);
}
// Wait for HTTP writes to complete.
closeHttpExecutorService(cacheBuckConfig, Optional.of(buildEventBus), httpWriteExecutorService);
closeExecutorService("CounterAggregatorExecutor", counterAggregatorExecutor, COUNTER_AGGREGATOR_SERVICE_TIMEOUT_SECONDS);
buildEventBus.post(CommandEvent.finished(startedEvent, exitCode));
} catch (Throwable t) {
LOG.debug(t, "Failing build on exception.");
closeHttpExecutorService(cacheBuckConfig, Optional.empty(), httpWriteExecutorService);
closeDiskIoExecutorService(diskIoExecutorService);
flushEventListeners(console, buildId, eventListeners);
throw t;
} finally {
if (commandSemaphoreAcquired) {
commandSemaphoreNgClient = Optional.empty();
BgProcessKiller.disarm();
// Allow another command to execute while outputting traces.
commandSemaphore.release();
commandSemaphoreAcquired = false;
}
if (isDaemon && shouldCleanUpTrash) {
// Clean up the trash in the background if this was a buckd
// read-write command. (We don't bother waiting for it to
// complete; the cleaner will ensure subsequent cleans are
// serialized with this one.)
TRASH_CLEANER.startCleaningDirectory(filesystem.getBuckPaths().getTrashDir());
}
// shut down the cached thread pools
for (ExecutorPool p : executors.keySet()) {
closeExecutorService(p.toString(), executors.get(p), EXECUTOR_SERVICES_TIMEOUT_SECONDS);
}
}
if (context.isPresent() && !rootCell.getBuckConfig().getFlushEventsBeforeExit()) {
// Avoid client exit triggering client disconnection handling.
context.get().in.close();
// Allow nailgun client to exit while outputting traces.
context.get().exit(exitCode);
}
closeDiskIoExecutorService(diskIoExecutorService);
flushEventListeners(console, buildId, eventListeners);
return exitCode;
}
} finally {
if (commandSemaphoreAcquired) {
commandSemaphoreNgClient = Optional.empty();
BgProcessKiller.disarm();
commandSemaphore.release();
}
}
}
Aggregations