| // Copyright 2014 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.runtime.commands; |
| |
| import com.google.devtools.build.lib.events.Event; |
| import com.google.devtools.build.lib.events.ExtendedEventHandler; |
| import com.google.devtools.build.lib.pkgcache.PackageCacheOptions; |
| import com.google.devtools.build.lib.pkgcache.PathPackageLocator; |
| import com.google.devtools.build.lib.runtime.BlazeCommand; |
| import com.google.devtools.build.lib.runtime.CommonCommandOptions; |
| import com.google.devtools.build.lib.runtime.ProjectFile; |
| import com.google.devtools.build.lib.skyframe.BazelSkyframeExecutorConstants; |
| import com.google.devtools.build.lib.vfs.Path; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| import com.google.devtools.build.lib.vfs.Root; |
| import com.google.devtools.common.options.OptionPriority.PriorityCategory; |
| import com.google.devtools.common.options.OptionsParser; |
| import com.google.devtools.common.options.OptionsParsingException; |
| import com.google.devtools.common.options.OptionsParsingResult; |
| import java.util.List; |
| |
| /** |
| * Provides support for implementations for {@link BlazeCommand} to work with {@link ProjectFile}. |
| */ |
| public final class ProjectFileSupport { |
| static final String PROJECT_FILE_PREFIX = "+"; |
| |
| private ProjectFileSupport() {} |
| |
| /** |
| * Reads any project files specified on the command line and updates the options parser |
| * accordingly. If project files cannot be read or if they contain unparsable options, or if they |
| * are not enabled, then it throws an exception instead. |
| */ |
| public static void handleProjectFiles( |
| ExtendedEventHandler eventHandler, ProjectFile.Provider projectFileProvider, |
| Path workspaceDir, Path workingDir, OptionsParser optionsParser, String command) |
| throws OptionsParsingException { |
| List<String> targets = optionsParser.getResidue(); |
| if (projectFileProvider != null && !targets.isEmpty() |
| && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) { |
| if (targets.size() > 1) { |
| throw new OptionsParsingException("Cannot handle more than one +<file> argument yet"); |
| } |
| if (!optionsParser.getOptions(CommonCommandOptions.class).allowProjectFiles) { |
| throw new OptionsParsingException("project file support is not enabled. " |
| + "Pass --experimental_allow_project_files to enable."); |
| } |
| // TODO(bazel-team): This is currently treated as a path relative to the workspace - if the |
| // cwd is a subdirectory of the workspace, that will be surprising, and we should interpret it |
| // relative to the cwd instead. |
| PathFragment projectFilePath = PathFragment.create(targets.get(0).substring(1)); |
| List<Root> packagePath = |
| PathPackageLocator.create( |
| // We only need a non-null outputBase for the PathPackageLocator if we support |
| // external |
| // repositories, which we don't for project files. |
| null, |
| optionsParser.getOptions(PackageCacheOptions.class).packagePath, |
| eventHandler, |
| workspaceDir, |
| workingDir, |
| BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY) |
| .getPathEntries(); |
| ProjectFile projectFile = projectFileProvider.getProjectFile( |
| workingDir, packagePath, projectFilePath, optionsParser); |
| eventHandler.handle(Event.info("Using " + projectFile.getName())); |
| |
| optionsParser.parse( |
| PriorityCategory.RC_FILE, projectFile.getName(), projectFile.getCommandLineFor(command)); |
| eventHandler.post(new GotProjectFileEvent(projectFile.getName())); |
| } |
| } |
| |
| /** |
| * Returns a list of targets from the options residue. If a project file is supplied as the first |
| * argument, it will be ignored, on the assumption that handleProjectFiles() has been called to |
| * process it. |
| */ |
| public static List<String> getTargets( |
| ProjectFile.Provider projectFileProvider, OptionsParsingResult options) { |
| List<String> targets = options.getResidue(); |
| if (projectFileProvider != null && !targets.isEmpty() |
| && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) { |
| return targets.subList(1, targets.size()); |
| } |
| return targets; |
| } |
| } |