blob: 114e7b0bb0b03521edf2cbb900dd31c10ff2ed9f [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
tomlu9a5d1af2018-02-15 13:11:08 -080015package com.google.devtools.build.lib.actions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010016
17import com.google.common.base.Joiner;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.Iterables;
Rumou Duan6d42e332016-05-19 15:33:38 +000020import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.devtools.build.lib.collect.CollectionUtils;
cpeyser10b1a5f2018-02-15 09:37:15 -080022import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
cpeyser10b1a5f2018-02-15 09:37:15 -080023import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
tomluac03ccf2018-01-29 14:28:29 -080024import com.google.devtools.build.lib.util.Fingerprint;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025
tomlu9a5d1af2018-02-15 13:11:08 -080026/** A representation of a list of arguments. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027public abstract class CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -080028 @AutoCodec
29 @VisibleForSerialization
30 static class EmptyCommandLine extends CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -080031 @Override
32 public Iterable<String> arguments() throws CommandLineExpansionException {
33 return ImmutableList.of();
34 }
35 }
36
37 public static final CommandLine EMPTY = new EmptyCommandLine();
Googlerd0e58c42017-05-24 22:20:45 +020038
tomlu3fb6ac32017-08-24 00:44:45 +020039 /** Returns the command line. */
40 public abstract Iterable<String> arguments() throws CommandLineExpansionException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041
42 /**
Rumou Duan6d42e332016-05-19 15:33:38 +000043 * Returns the evaluated command line with enclosed artifacts expanded by {@code artifactExpander}
44 * at execution time.
45 *
46 * <p>By default, this method just delegates to {@link #arguments()}, without performing any
47 * artifact expansion. Subclasses should override this method if they contain TreeArtifacts and
48 * need to expand them for proper argument evaluation.
49 */
tomlu3fb6ac32017-08-24 00:44:45 +020050 public Iterable<String> arguments(ArtifactExpander artifactExpander)
51 throws CommandLineExpansionException {
Rumou Duan6d42e332016-05-19 15:33:38 +000052 return arguments();
53 }
54
tomluac03ccf2018-01-29 14:28:29 -080055 public void addToFingerprint(ActionKeyContext actionKeyContext, Fingerprint fingerprint)
56 throws CommandLineExpansionException {
57 for (String s : arguments()) {
58 fingerprint.addString(s);
59 }
60 }
61
cpeyser10b1a5f2018-02-15 09:37:15 -080062 @AutoCodec
63 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -080064 static class SimpleCommandLine extends CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -080065 private Iterable<String> args;
66
tomlubf6c2672018-02-20 07:06:05 -080067 SimpleCommandLine(Iterable<String> args) {
cpeyser10b1a5f2018-02-15 09:37:15 -080068 this.args = args;
69 }
70
71 @Override
72 public Iterable<String> arguments() throws CommandLineExpansionException {
73 return args;
74 }
75 }
76
Googler48034fd2017-05-15 18:05:46 +020077 /** Returns a {@link CommandLine} backed by a copy of the given list of arguments. */
78 public static CommandLine of(Iterable<String> arguments) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079 final Iterable<String> immutableArguments = CollectionUtils.makeImmutable(arguments);
tomlubf6c2672018-02-20 07:06:05 -080080 return new SimpleCommandLine(immutableArguments);
cpeyser10b1a5f2018-02-15 09:37:15 -080081 }
82
83 @AutoCodec
84 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -080085 static class PrefixedCommandLine extends CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -080086 private ImmutableList<String> executableArgs;
87 private CommandLine commandLine;
88
89 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -080090 PrefixedCommandLine(ImmutableList<String> executableArgs, CommandLine commandLine) {
cpeyser10b1a5f2018-02-15 09:37:15 -080091 this.executableArgs = executableArgs;
92 this.commandLine = commandLine;
93 }
94
95 @Override
96 public Iterable<String> arguments() throws CommandLineExpansionException {
97 return Iterables.concat(executableArgs, commandLine.arguments());
98 }
99
100 @Override
101 public Iterable<String> arguments(ArtifactExpander artifactExpander)
102 throws CommandLineExpansionException {
103 return Iterables.concat(executableArgs, commandLine.arguments(artifactExpander));
104 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100105 }
106
107 /**
108 * Returns a {@link CommandLine} that is constructed by prepending the {@code executableArgs} to
109 * {@code commandLine}.
110 */
Googlerd0e58c42017-05-24 22:20:45 +0200111 public static CommandLine concat(
112 final ImmutableList<String> executableArgs, final CommandLine commandLine) {
113 if (executableArgs.isEmpty()) {
114 return commandLine;
115 }
tomlubf6c2672018-02-20 07:06:05 -0800116 return new PrefixedCommandLine(executableArgs, commandLine);
cpeyser10b1a5f2018-02-15 09:37:15 -0800117 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100118
cpeyser10b1a5f2018-02-15 09:37:15 -0800119 @AutoCodec
120 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -0800121 static class SuffixedCommandLine extends CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -0800122 private ImmutableList<String> executableArgs;
123 private CommandLine commandLine;
124
125 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -0800126 SuffixedCommandLine(ImmutableList<String> executableArgs, CommandLine commandLine) {
cpeyser10b1a5f2018-02-15 09:37:15 -0800127 this.executableArgs = executableArgs;
128 this.commandLine = commandLine;
129 }
130
131 @Override
132 public Iterable<String> arguments() throws CommandLineExpansionException {
133 return Iterables.concat(commandLine.arguments(), executableArgs);
134 }
135
136 @Override
137 public Iterable<String> arguments(ArtifactExpander artifactExpander)
138 throws CommandLineExpansionException {
139 return Iterables.concat(commandLine.arguments(artifactExpander), executableArgs);
140 }
Googlerd0e58c42017-05-24 22:20:45 +0200141 }
142
143 /**
144 * Returns a {@link CommandLine} that is constructed by appending the {@code args} to {@code
145 * commandLine}.
146 */
147 public static CommandLine concat(
148 final CommandLine commandLine, final ImmutableList<String> args) {
149 if (args.isEmpty()) {
150 return commandLine;
151 }
tomlubf6c2672018-02-20 07:06:05 -0800152 return new SuffixedCommandLine(args, commandLine);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100153 }
154
155 /**
156 * This helps when debugging Blaze code that uses {@link CommandLine}s, as you can see their
157 * content directly in the variable inspector.
158 */
159 @Override
160 public String toString() {
tomlu3fb6ac32017-08-24 00:44:45 +0200161 try {
162 return Joiner.on(' ').join(arguments());
163 } catch (CommandLineExpansionException e) {
164 return "Error in expanding command line";
165 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100166 }
167}