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