blob: 1516fb01b73cff20085ffbb6afa02d87555898ce [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;
Rumou Duan6d42e332016-05-19 15:33:38 +000019import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.devtools.build.lib.collect.CollectionUtils;
cushon9fe597d2018-10-23 12:39:08 -070021import com.google.devtools.build.lib.collect.IterablesChain;
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 {
cushon9fe597d2018-10-23 12:39:08 -070097 return IterablesChain.concat(executableArgs, commandLine.arguments());
cpeyser10b1a5f2018-02-15 09:37:15 -080098 }
99
100 @Override
101 public Iterable<String> arguments(ArtifactExpander artifactExpander)
102 throws CommandLineExpansionException {
cushon9fe597d2018-10-23 12:39:08 -0700103 return IterablesChain.concat(executableArgs, commandLine.arguments(artifactExpander));
cpeyser10b1a5f2018-02-15 09:37:15 -0800104 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100105 }
106
cpeyser10b1a5f2018-02-15 09:37:15 -0800107 @AutoCodec
108 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -0800109 static class SuffixedCommandLine extends CommandLine {
cpeyser10b1a5f2018-02-15 09:37:15 -0800110 private ImmutableList<String> executableArgs;
111 private CommandLine commandLine;
112
113 @VisibleForSerialization
tomlubf6c2672018-02-20 07:06:05 -0800114 SuffixedCommandLine(ImmutableList<String> executableArgs, CommandLine commandLine) {
cpeyser10b1a5f2018-02-15 09:37:15 -0800115 this.executableArgs = executableArgs;
116 this.commandLine = commandLine;
117 }
118
119 @Override
120 public Iterable<String> arguments() throws CommandLineExpansionException {
cushon9fe597d2018-10-23 12:39:08 -0700121 return IterablesChain.concat(commandLine.arguments(), executableArgs);
cpeyser10b1a5f2018-02-15 09:37:15 -0800122 }
123
124 @Override
125 public Iterable<String> arguments(ArtifactExpander artifactExpander)
126 throws CommandLineExpansionException {
cushon9fe597d2018-10-23 12:39:08 -0700127 return IterablesChain.concat(commandLine.arguments(artifactExpander), executableArgs);
cpeyser10b1a5f2018-02-15 09:37:15 -0800128 }
Googlerd0e58c42017-05-24 22:20:45 +0200129 }
130
131 /**
lberkide5e9682018-10-19 01:20:34 -0700132 * Returns a {@link CommandLine} that is constructed by prepending the {@code executableArgs} to
133 * {@code commandLine}.
134 */
135 public static CommandLine concat(
136 final ImmutableList<String> executableArgs, final CommandLine commandLine) {
137 if (executableArgs.isEmpty()) {
138 return commandLine;
139 }
cushon9fe597d2018-10-23 12:39:08 -0700140 if (commandLine == EMPTY) {
141 return CommandLine.of(executableArgs);
142 }
lberkide5e9682018-10-19 01:20:34 -0700143 return new PrefixedCommandLine(executableArgs, commandLine);
144 }
145
146 /**
Googlerd0e58c42017-05-24 22:20:45 +0200147 * Returns a {@link CommandLine} that is constructed by appending the {@code args} to {@code
148 * commandLine}.
149 */
150 public static CommandLine concat(
151 final CommandLine commandLine, final ImmutableList<String> args) {
152 if (args.isEmpty()) {
153 return commandLine;
154 }
cushon9fe597d2018-10-23 12:39:08 -0700155 if (commandLine == EMPTY) {
156 return CommandLine.of(args);
157 }
tomlubf6c2672018-02-20 07:06:05 -0800158 return new SuffixedCommandLine(args, commandLine);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100159 }
160
161 /**
162 * This helps when debugging Blaze code that uses {@link CommandLine}s, as you can see their
163 * content directly in the variable inspector.
164 */
165 @Override
166 public String toString() {
tomlu3fb6ac32017-08-24 00:44:45 +0200167 try {
168 return Joiner.on(' ').join(arguments());
169 } catch (CommandLineExpansionException e) {
170 return "Error in expanding command line";
171 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100172 }
173}