]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssembler.java
Changed spelling to manifest
[mirror_edk2.git] / Tools / Source / Cpptasks / net / sf / antcontrib / cpptasks / compiler / CommandLineAssembler.java
1 /*
2 *
3 * Copyright 2001-2005 The Ant-Contrib project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package net.sf.antcontrib.cpptasks.compiler;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.Enumeration;
22 import java.util.Vector;
23
24 import net.sf.antcontrib.cpptasks.AssemblerDef;
25 import net.sf.antcontrib.cpptasks.CCTask;
26 import net.sf.antcontrib.cpptasks.CUtil;
27 import net.sf.antcontrib.cpptasks.ProcessorDef;
28 import net.sf.antcontrib.cpptasks.TargetDef;
29 import net.sf.antcontrib.cpptasks.types.CommandLineArgument;
30
31 import org.apache.tools.ant.BuildException;
32
33 /**
34 * An abstract Assembler implementation which uses an external program to
35 * perform the assemble.
36 *
37 */
38 public abstract class CommandLineAssembler extends AbstractAssembler {
39
40 private String command;
41
42 private String identifier;
43
44 private String identifierArg;
45
46 protected CommandLineAssembler (String command, String identifierArg,
47 String[] sourceExtensions, String[] headerExtensions,
48 String outputSuffix) {
49 super(sourceExtensions, headerExtensions, outputSuffix);
50 this.command = command;
51 this.identifierArg = identifierArg;
52 }
53
54 abstract protected void addImpliedArgs(Vector args, boolean debug,
55 Boolean defaultflag);
56
57 /**
58 * Adds command-line arguments for include directories.
59 *
60 * If relativeArgs is not null will add corresponding relative paths include
61 * switches to that vector (for use in building a configuration identifier
62 * that is consistent between machines).
63 *
64 * @param baseDirPaths
65 * A vector containing the parts of the working directory,
66 * produced by CUtil.DecomposeFile.
67 * @param includeDirs
68 * Array of include directory paths
69 * @param args
70 * Vector of command line arguments used to execute the task
71 * @param relativeArgs
72 * Vector of command line arguments used to build the
73 * configuration identifier
74 */
75 protected void addIncludes(String baseDirPath, File[] includeDirs,
76 Vector args, Vector relativeArgs, StringBuffer includePathId) {
77 for (int i = 0; i < includeDirs.length; i++) {
78 args.addElement(getIncludeDirSwitch(includeDirs[i]
79 .getAbsolutePath()));
80 if (relativeArgs != null) {
81 String relative = CUtil.getRelativePath(baseDirPath,
82 includeDirs[i]);
83 relativeArgs.addElement(getIncludeDirSwitch(relative));
84 if (includePathId != null) {
85 if (includePathId.length() == 0) {
86 includePathId.append("/I");
87 } else {
88 includePathId.append(" /I");
89 }
90 includePathId.append(relative);
91 }
92 }
93 }
94 }
95
96 abstract protected String getIncludeDirSwitch(String source);
97
98 /**
99 * Assembles a source file
100 *
101 */
102 public void assembler(CCTask task, File outputDir, String[] sourceFiles,
103 String[] args, String[] endArgs) throws BuildException {
104 String command = getCommand();
105 int baseLength = command.length() + args.length + endArgs.length;
106 for (int i = 0; i < args.length; i++) {
107 baseLength += args[i].length();
108 }
109 for (int i = 0; i < endArgs.length; i++) {
110 baseLength += endArgs[i].length();
111 }
112 if (baseLength > getMaximumCommandLength()) {
113 throw new BuildException(
114 "Command line is over maximum length without sepcifying source file");
115 }
116 int maxInputFilesPerCommand = getMaximumInputFilesPerCommand();
117 int argumentCountPerInputFile = getArgumentCountPerInputFIle();
118 for (int sourceIndex = 0; sourceIndex < sourceFiles.length;) {
119 int cmdLength = baseLength;
120 int firstFileNextExec;
121 for (firstFileNextExec = sourceIndex; firstFileNextExec < sourceFiles.length
122 && (firstFileNextExec - sourceIndex) < maxInputFilesPerCommand; firstFileNextExec++) {
123 cmdLength += getTotalArgumentLengthForInputFile(outputDir,
124 sourceFiles[firstFileNextExec]);
125 if (cmdLength >= getMaximumCommandLength())
126 break;
127 }
128 if (firstFileNextExec == sourceIndex) {
129 throw new BuildException(
130 "Extremely long file name, can't fit on command line");
131 }
132 int argCount = args.length + 1 + endArgs.length
133 + (firstFileNextExec - sourceIndex)
134 * argumentCountPerInputFile;
135 String[] commandline = new String[argCount];
136 int index = 0;
137 commandline[index++] = command;
138 for (int j = 0; j < args.length; j++) {
139 commandline[index++] = args[j];
140 }
141 for (int j = sourceIndex; j < firstFileNextExec; j++) {
142 for (int k = 0; k < argumentCountPerInputFile; k++) {
143 commandline[index++] = getInputFileArgument(outputDir,
144 sourceFiles[j], k);
145 }
146 }
147 for (int j = 0; j < endArgs.length; j++) {
148 commandline[index++] = endArgs[j];
149 }
150 int retval = runCommand(task, outputDir, commandline);
151 // if with monitor, add more code
152 if (retval != 0) {
153 throw new BuildException(this.getCommand()
154 + " failed with return code " + retval, task
155 .getLocation());
156 }
157 sourceIndex = firstFileNextExec;
158 }
159 }
160
161 protected AssemblerConfiguration createConfiguration(final CCTask task,
162 final LinkType linkType, final ProcessorDef[] baseDefs,
163 final AssemblerDef specificDef,
164 final TargetDef targetPlatform) {
165 Vector args = new Vector();
166 AssemblerDef[] defaultProviders = new AssemblerDef[baseDefs.length + 1];
167 for (int i = 0; i < baseDefs.length; i++) {
168 defaultProviders[i + 1] = (AssemblerDef) baseDefs[i];
169 }
170 defaultProviders[0] = specificDef;
171 Vector cmdArgs = new Vector();
172 //
173 // add command line arguments inherited from <cc> element
174 // any "extends" and finally and specific AssemblerDef
175 //
176 CommandLineArgument[] commandArgs;
177 for (int i = defaultProviders.length - 1; i >= 0; i--) {
178 commandArgs = defaultProviders[i].getActiveProcessorArgs();
179 for (int j = 0; j < commandArgs.length; j++) {
180 if (commandArgs[j].getLocation() == 0) {
181 args.addElement(commandArgs[j].getValue());
182 } else {
183 cmdArgs.addElement(commandArgs[j]);
184 }
185 }
186 }
187 // omit param
188 boolean debug = specificDef.getDebug(baseDefs, 0);
189 Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1);
190 this.addImpliedArgs(args, debug, defaultflag);
191 //
192 // Want to have distinct set of arguments with relative
193 // path names for includes that are used to build
194 // the configuration identifier
195 //
196 Vector relativeArgs = (Vector) args.clone();
197 //
198 // add all active include an
199 //
200 StringBuffer includePathIdentifier = new StringBuffer();
201 File baseDir = specificDef.getProject().getBaseDir();
202 String baseDirPath;
203 try {
204 baseDirPath = baseDir.getCanonicalPath();
205 } catch (IOException ex) {
206 baseDirPath = baseDir.toString();
207 }
208 Vector includePath = new Vector();
209 Vector sysIncludePath = new Vector();
210 for (int i = defaultProviders.length - 1; i >= 0; i--) {
211 String[] incPath = defaultProviders[i].getActiveIncludePaths();
212 for (int j = 0; j < incPath.length; j++) {
213 includePath.addElement(incPath[j]);
214 }
215 incPath = defaultProviders[i].getActiveSysIncludePaths();
216 for (int j = 0; j < incPath.length; j++) {
217 sysIncludePath.addElement(incPath[j]);
218 }
219 }
220 File[] incPath = new File[includePath.size()];
221 for (int i = 0; i < includePath.size(); i++) {
222 incPath[i] = new File((String) includePath.elementAt(i));
223 }
224 File[] sysIncPath = new File[sysIncludePath.size()];
225 for (int i = 0; i < sysIncludePath.size(); i++) {
226 sysIncPath[i] = new File((String) sysIncludePath.elementAt(i));
227 }
228 addIncludes(baseDirPath, incPath, args, relativeArgs,
229 includePathIdentifier);
230 addIncludes(baseDirPath, sysIncPath, args, null, null);
231 StringBuffer buf = new StringBuffer(getIdentifier());
232 for (int i = 0; i < relativeArgs.size(); i++) {
233 buf.append(relativeArgs.elementAt(i));
234 buf.append(' ');
235 }
236 buf.setLength(buf.length() - 1);
237 Enumeration argEnum = cmdArgs.elements();
238 int endCount = 0;
239 while (argEnum.hasMoreElements()) {
240 CommandLineArgument arg = (CommandLineArgument) argEnum
241 .nextElement();
242 switch (arg.getLocation()) {
243 case 1:
244 args.addElement(arg.getValue());
245 break;
246 case 2:
247 endCount++;
248 break;
249 }
250 }
251 String[] endArgs = new String[endCount];
252 argEnum = cmdArgs.elements();
253 int index = 0;
254 while (argEnum.hasMoreElements()) {
255 CommandLineArgument arg = (CommandLineArgument) argEnum
256 .nextElement();
257 if (arg.getLocation() == 2) {
258 endArgs[index++] = arg.getValue();
259 }
260 }
261 String[] argArray = new String[args.size()];
262 args.copyInto(argArray);
263 return new CommandLineAssemblerConfiguration(this, incPath, sysIncPath,
264 new File[0], argArray, true, endArgs, new String[0]);
265 }
266
267 protected int getArgumentCountPerInputFile() {
268 return 1;
269 }
270
271 protected abstract File[] getEnvironmentIncludePath();
272
273 public String getIdentifier() {
274 if (identifier == null) {
275 if (identifierArg == null) {
276 identifier = getIdentifier(new String[] { command }, command);
277 } else {
278 identifier = getIdentifier(new String[] { command,
279 identifierArg }, command);
280 }
281 }
282 return identifier;
283 }
284
285 public final String getCommand() {
286 return command;
287 }
288
289 abstract public int getMaximumCommandLength();
290
291 public void setCommand(String command) {
292 this.command = command;
293 }
294
295 protected int getTotalArgumentLengthForInputFile(File outputDir,
296 String inputFile) {
297 return inputFile.length() + 1;
298 }
299
300 protected int runCommand(CCTask task, File workingDir, String[] cmdline)
301 throws BuildException {
302 return CUtil.runCommand(task, workingDir, cmdline, false, null);
303 }
304
305 protected int getMaximumInputFilesPerCommand() {
306 return Integer.MAX_VALUE;
307 }
308
309 protected int getArgumentCountPerInputFIle() {
310 return 1;
311 }
312
313 protected String getInputFileArgument(File outputDir, String filename,
314 int index) {
315 //
316 // if there is an embedded space,
317 // must enclose in quotes
318 if (filename.indexOf(' ') >= 0) {
319 StringBuffer buf = new StringBuffer("\"");
320 buf.append(filename);
321 buf.append("\"");
322 return buf.toString();
323 }
324 return filename;
325 }
326 }