comparison src/share/tools/ProjectCreator/WinGammaPlatformVC7.java @ 2044:06f017f7daa7

Merge.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Fri, 07 Jan 2011 18:18:08 +0100
parents src/share/tools/MakeDeps/WinGammaPlatformVC7.java@2d26b0046e0d src/share/tools/MakeDeps/WinGammaPlatformVC7.java@aa6e219afbf1
children 2ab52cda08e5
comparison
equal deleted inserted replaced
1942:00bc9eaf0e24 2044:06f017f7daa7
1 /*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.PrintWriter;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.TreeSet;
31 import java.util.Vector;
32
33 public class WinGammaPlatformVC7 extends WinGammaPlatform {
34
35 String projectVersion() {return "7.10";};
36
37 public void writeProjectFile(String projectFileName, String projectName,
38 Vector allConfigs) throws IOException {
39 System.out.println();
40 System.out.println(" Writing .vcproj file...");
41 // If we got this far without an error, we're safe to actually
42 // write the .vcproj file
43 printWriter = new PrintWriter(new FileWriter(projectFileName));
44
45 printWriter.println("<?xml version=\"1.0\" encoding=\"windows-1251\"?>");
46 startTag(
47 "VisualStudioProject",
48 new String[] {
49 "ProjectType", "Visual C++",
50 "Version", projectVersion(),
51 "Name", projectName,
52 "ProjectGUID", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}",
53 "SccProjectName", "",
54 "SccLocalPath", ""
55 }
56 );
57
58 startTag("Platforms", null);
59 tag("Platform", new String[] {"Name", Util.os()});
60 endTag("Platforms");
61
62 startTag("Configurations", null);
63
64 for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
65 writeConfiguration((BuildConfig)i.next());
66 }
67
68 endTag("Configurations");
69
70 tag("References", null);
71
72 writeFiles(allConfigs);
73
74 tag("Globals", null);
75
76 endTag("VisualStudioProject");
77 printWriter.close();
78
79 System.out.println(" Done.");
80 }
81
82
83 abstract class NameFilter {
84 protected String fname;
85
86 abstract boolean match(FileInfo fi);
87
88 String filterString() { return ""; }
89 String name() { return this.fname;}
90 }
91
92 class DirectoryFilter extends NameFilter {
93 String dir;
94 int baseLen, dirLen;
95
96 DirectoryFilter(String dir, String sbase) {
97 this.dir = dir;
98 this.baseLen = sbase.length();
99 this.dirLen = dir.length();
100 this.fname = dir;
101 }
102
103 DirectoryFilter(String fname, String dir, String sbase) {
104 this.dir = dir;
105 this.baseLen = sbase.length();
106 this.dirLen = dir.length();
107 this.fname = fname;
108 }
109
110
111 boolean match(FileInfo fi) {
112 int lastSlashIndex = fi.full.lastIndexOf('/');
113 String fullDir = fi.full.substring(0, lastSlashIndex);
114 return fullDir.endsWith(dir);
115 }
116 }
117
118 class TypeFilter extends NameFilter {
119 String[] exts;
120
121 TypeFilter(String fname, String[] exts) {
122 this.fname = fname;
123 this.exts = exts;
124 }
125
126 boolean match(FileInfo fi) {
127 for (int i=0; i<exts.length; i++) {
128 if (fi.full.endsWith(exts[i])) {
129 return true;
130 }
131 }
132 return false;
133 }
134
135 String filterString() {
136 return Util.join(";", exts);
137 }
138 }
139
140 class TerminatorFilter extends NameFilter {
141 TerminatorFilter(String fname) {
142 this.fname = fname;
143
144 }
145 boolean match(FileInfo fi) {
146 return true;
147 }
148
149 }
150
151 class SpecificNameFilter extends NameFilter {
152 String pats[];
153
154 SpecificNameFilter(String fname, String[] pats) {
155 this.fname = fname;
156 this.pats = pats;
157 }
158
159 boolean match(FileInfo fi) {
160 for (int i=0; i<pats.length; i++) {
161 if (fi.attr.shortName.matches(pats[i])) {
162 return true;
163 }
164 }
165 return false;
166 }
167
168 }
169
170 class SpecificPathFilter extends NameFilter {
171 String pats[];
172
173 SpecificPathFilter(String fname, String[] pats) {
174 this.fname = fname;
175 this.pats = pats;
176 }
177
178 boolean match(FileInfo fi) {
179 for (int i=0; i<pats.length; i++) {
180 if (fi.full.matches(pats[i])) {
181 return true;
182 }
183 }
184 return false;
185 }
186
187 }
188
189 class ContainerFilter extends NameFilter {
190 Vector children;
191
192 ContainerFilter(String fname) {
193 this.fname = fname;
194 children = new Vector();
195
196 }
197 boolean match(FileInfo fi) {
198 return false;
199 }
200
201 Iterator babies() { return children.iterator(); }
202
203 void add(NameFilter f) {
204 children.add(f);
205 }
206 }
207
208
209 void writeCustomToolConfig(Vector configs, String[] customToolAttrs) {
210 for (Iterator i = configs.iterator(); i.hasNext(); ) {
211 startTag("FileConfiguration",
212 new String[] {
213 "Name", (String)i.next()
214 }
215 );
216 tag("Tool", customToolAttrs);
217
218 endTag("FileConfiguration");
219 }
220 }
221
222 // here we define filters, which define layout of what can be seen in 'Solution View' of MSVC
223 // Basically there are two types of entities - container filters and real filters
224 // - container filter just provides a container to group together real filters
225 // - real filter can select elements from the set according to some rule, put it into XML
226 // and remove from the list
227 Vector makeFilters(TreeSet<FileInfo> files) {
228 Vector rv = new Vector();
229 String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/");
230
231 String currentDir = "";
232 DirectoryFilter container = null;
233 for(FileInfo fileInfo : files) {
234
235 if (!fileInfo.full.startsWith(sbase)) {
236 continue;
237 }
238
239 int lastSlash = fileInfo.full.lastIndexOf('/');
240 String dir = fileInfo.full.substring(sbase.length(), lastSlash);
241 if(dir.equals("share/vm")) {
242 // skip files directly in share/vm - should only be precompiled.hpp which is handled below
243 continue;
244 }
245 if (!dir.equals(currentDir)) {
246 currentDir = dir;
247 if (container != null) {
248 rv.add(container);
249 }
250
251 // remove "share/vm/" from names
252 String name = dir;
253 if (dir.startsWith("share/vm/")) {
254 name = dir.substring("share/vm/".length(), dir.length());
255 }
256 container = new DirectoryFilter(name, dir, sbase);
257 }
258 }
259 if (container != null) {
260 rv.add(container);
261 }
262
263 rv.add(new DirectoryFilter("C1X", "share/vm/c1x", sbase));
264 rv.add(new DirectoryFilter("C1", "share/vm/c1", sbase));
265
266 ContainerFilter generated = new ContainerFilter("Generated");
267 ContainerFilter c1Generated = new ContainerFilter("C1");
268 c1Generated.add(new SpecificPathFilter("C++ Interpreter Generated", new String[] {".*compiler1/generated/jvmtifiles/bytecodeInterpreterWithChecks.+"}));
269 c1Generated.add(new SpecificPathFilter("jvmtifiles", new String[] {".*compiler1/generated/jvmtifiles/.*"}));
270 generated.add(c1Generated);
271 ContainerFilter c2Generated = new ContainerFilter("C2");
272 c2Generated.add(new SpecificPathFilter("C++ Interpreter Generated", new String[] {".*compiler2/generated/jvmtifiles/bytecodeInterpreterWithChecks.+"}));
273 c2Generated.add(new SpecificPathFilter("adfiles", new String[] {".*compiler2/generated/adfiles/.*"}));
274 c2Generated.add(new SpecificPathFilter("jvmtifiles", new String[] {".*compiler2/generated/jvmtifiles/.*"}));
275 generated.add(c2Generated);
276 ContainerFilter coreGenerated = new ContainerFilter("Core");
277 coreGenerated.add(new SpecificPathFilter("C++ Interpreter Generated", new String[] {".*core/generated/jvmtifiles/bytecodeInterpreterWithChecks.+"}));
278 coreGenerated.add(new SpecificPathFilter("jvmtifiles", new String[] {".*core/generated/jvmtifiles/.*"}));
279 generated.add(coreGenerated);
280 ContainerFilter tieredGenerated = new ContainerFilter("Tiered");
281 tieredGenerated.add(new SpecificPathFilter("C++ Interpreter Generated", new String[] {".*tiered/generated/jvmtifiles/bytecodeInterpreterWithChecks.+"}));
282 tieredGenerated.add(new SpecificPathFilter("adfiles", new String[] {".*tiered/generated/adfiles/.*"}));
283 tieredGenerated.add(new SpecificPathFilter("jvmtifiles", new String[] {".*tiered/generated/jvmtifiles/.*"}));
284 generated.add(tieredGenerated);
285 ContainerFilter kernelGenerated = new ContainerFilter("Kernel");
286 kernelGenerated.add(new SpecificPathFilter("C++ Interpreter Generated", new String[] {".*kernel/generated/jvmtifiles/bytecodeInterpreterWithChecks.+"}));
287 kernelGenerated.add(new SpecificPathFilter("jvmtifiles", new String[] {".*kernel/generated/jvmtifiles/.*"}));
288 generated.add(kernelGenerated);
289 rv.add(generated);
290
291 rv.add(new SpecificNameFilter("Precompiled Header", new String[] {"precompiled.hpp"}));
292
293 // this one is to catch files not caught by other filters
294 //rv.add(new TypeFilter("Header Files", new String[] {"h", "hpp", "hxx", "hm", "inl", "fi", "fd"}));
295 rv.add(new TerminatorFilter("Source Files"));
296
297 return rv;
298 }
299
300 void writeFiles(Vector allConfigs) {
301
302 Hashtable allFiles = computeAttributedFiles(allConfigs);
303
304 Vector allConfigNames = new Vector();
305 for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
306 allConfigNames.add(((BuildConfig)i.next()).get("Name"));
307 }
308
309 TreeSet sortedFiles = sortFiles(allFiles);
310
311 startTag("Files", null);
312
313 for (Iterator i = makeFilters(sortedFiles).iterator(); i.hasNext(); ) {
314 doWriteFiles(sortedFiles, allConfigNames, (NameFilter)i.next());
315 }
316
317
318 startTag("Filter",
319 new String[] {
320 "Name", "Resource Files",
321 "Filter", "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
322 }
323 );
324 endTag("Filter");
325
326 endTag("Files");
327 }
328
329 void doWriteFiles(TreeSet allFiles, Vector allConfigNames, NameFilter filter) {
330 startTag("Filter",
331 new String[] {
332 "Name", filter.name(),
333 "Filter", filter.filterString()
334 }
335 );
336
337 if (filter instanceof ContainerFilter) {
338
339 Iterator i = ((ContainerFilter)filter).babies();
340 while (i.hasNext()) {
341 doWriteFiles(allFiles, allConfigNames, (NameFilter)i.next());
342 }
343
344 } else {
345
346 Iterator i = allFiles.iterator();
347 while (i.hasNext()) {
348 FileInfo fi = (FileInfo)i.next();
349
350 if (!filter.match(fi)) {
351 continue;
352 }
353
354 startTag("File",
355 new String[] {
356 "RelativePath", fi.full.replace('/', '\\')
357 }
358 );
359
360 FileAttribute a = fi.attr;
361 if (a.pchRoot) {
362 writeCustomToolConfig(allConfigNames,
363 new String[] {
364 "Name", "VCCLCompilerTool",
365 "UsePrecompiledHeader", "1"
366 });
367 }
368
369 if (a.noPch) {
370 writeCustomToolConfig(allConfigNames,
371 new String[] {
372 "Name", "VCCLCompilerTool",
373 "UsePrecompiledHeader", "0"
374 });
375 }
376
377 if (a.configs != null) {
378 for (Iterator j=allConfigNames.iterator(); j.hasNext();) {
379 String cfg = (String)j.next();
380 if (!a.configs.contains(cfg)) {
381 startTag("FileConfiguration",
382 new String[] {
383 "Name", cfg,
384 "ExcludedFromBuild", "TRUE"
385 });
386 endTag("FileConfiguration");
387
388 }
389 }
390 }
391
392 endTag("File");
393
394 // we not gonna look at this file anymore
395 i.remove();
396 }
397 }
398
399 endTag("Filter");
400 }
401
402
403 void writeConfiguration(BuildConfig cfg) {
404 startTag("Configuration",
405 new String[] {
406 "Name", cfg.get("Name"),
407 "OutputDirectory", cfg.get("OutputDir"),
408 "IntermediateDirectory", cfg.get("OutputDir"),
409 "ConfigurationType", "2",
410 "UseOfMFC", "0",
411 "ATLMinimizesCRunTimeLibraryUsage", "FALSE"
412 }
413 );
414
415
416
417 tagV("Tool", cfg.getV("CompilerFlags"));
418
419 tag("Tool",
420 new String[] {
421 "Name", "VCCustomBuildTool"
422 }
423 );
424
425 tagV("Tool", cfg.getV("LinkerFlags"));
426
427 tag("Tool",
428 new String[] {
429 "Name", "VCPostBuildEventTool",
430 "Description", BuildConfig.getFieldString(null, "PostbuildDescription"),
431 //Caution: String.replace(String,String) is available from JDK5 onwards only
432 "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace
433 ("\t", "&#x0D;&#x0A;"))
434 }
435 );
436
437 tag("Tool",
438 new String[] {
439 "Name", "VCPreBuildEventTool"
440 }
441 );
442
443 tag("Tool",
444 new String[] {
445 "Name", "VCPreLinkEventTool",
446 "Description", BuildConfig.getFieldString(null, "PrelinkDescription"),
447 //Caution: String.replace(String,String) is available from JDK5 onwards only
448 "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace
449 ("\t", "&#x0D;&#x0A;"))
450 }
451 );
452
453 tag("Tool",
454 new String[] {
455 "Name", "VCResourceCompilerTool",
456 // XXX???
457 "PreprocessorDefinitions", "NDEBUG",
458 "Culture", "1033"
459 }
460 );
461
462 tag("Tool",
463 new String[] {
464 "Name", "VCMIDLTool",
465 "PreprocessorDefinitions", "NDEBUG",
466 "MkTypLibCompatible", "TRUE",
467 "SuppressStartupBanner", "TRUE",
468 "TargetEnvironment", Util.os().equals("Win32") ? "1" : "3",
469 "TypeLibraryName", cfg.get("OutputDir") + Util.sep + "vm.tlb",
470 "HeaderFileName", ""
471 }
472 );
473
474 endTag("Configuration");
475 }
476
477 int indent;
478
479 private void startTagPrim(String name,
480 String[] attrs,
481 boolean close) {
482 doIndent();
483 printWriter.print("<"+name);
484 indent++;
485
486 if (attrs != null) {
487 printWriter.println();
488 for (int i=0; i<attrs.length; i+=2) {
489 doIndent();
490 printWriter.print(" " + attrs[i]+"=\""+attrs[i+1]+"\"");
491 if (i < attrs.length - 2) {
492 printWriter.println();
493 }
494 }
495 }
496
497 if (close) {
498 indent--;
499 //doIndent();
500 printWriter.println("/>");
501 } else {
502 //doIndent();
503 printWriter.println(">");
504 }
505 }
506
507 void startTag(String name, String[] attrs) {
508 startTagPrim(name, attrs, false);
509 }
510
511 void startTagV(String name, Vector attrs) {
512 String s[] = new String [attrs.size()];
513 for (int i=0; i<attrs.size(); i++) {
514 s[i] = (String)attrs.elementAt(i);
515 }
516 startTagPrim(name, s, false);
517 }
518
519 void endTag(String name) {
520 indent--;
521 doIndent();
522 printWriter.println("</"+name+">");
523 }
524
525 void tag(String name, String[] attrs) {
526 startTagPrim(name, attrs, true);
527 }
528
529 void tagV(String name, Vector attrs) {
530 String s[] = new String [attrs.size()];
531 for (int i=0; i<attrs.size(); i++) {
532 s[i] = (String)attrs.elementAt(i);
533 }
534 startTagPrim(name, s, true);
535 }
536
537
538 void doIndent() {
539 for (int i=0; i<indent; i++) {
540 printWriter.print(" ");
541 }
542 }
543
544 protected String getProjectExt() {
545 return ".vcproj";
546 }
547 }
548
549 class CompilerInterfaceVC7 extends CompilerInterface {
550 void getBaseCompilerFlags_common(Vector defines, Vector includes, String outDir,Vector rv) {
551
552 // advanced M$ IDE (2003) can only recognize name if it's first or
553 // second attribute in the tag - go guess
554 addAttr(rv, "Name", "VCCLCompilerTool");
555 addAttr(rv, "AdditionalIncludeDirectories", Util.join(",", includes));
556 addAttr(rv, "PreprocessorDefinitions",
557 Util.join(";", defines).replace("\"","&quot;"));
558 addAttr(rv, "PrecompiledHeaderThrough", "precompiled.hpp");
559 addAttr(rv, "PrecompiledHeaderFile", outDir+Util.sep+"vm.pch");
560 addAttr(rv, "AssemblerListingLocation", outDir);
561 addAttr(rv, "ObjectFile", outDir+Util.sep);
562 addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"jvm.pdb");
563 // Set /nologo optin
564 addAttr(rv, "SuppressStartupBanner", "TRUE");
565 // Surpass the default /Tc or /Tp. 0 is compileAsDefault
566 addAttr(rv, "CompileAs", "0");
567 // Set /W3 option. 3 is warningLevel_3
568 addAttr(rv, "WarningLevel", "3");
569 // Set /WX option,
570 addAttr(rv, "WarnAsError", "TRUE");
571 // Set /GS option
572 addAttr(rv, "BufferSecurityCheck", "FALSE");
573 // Set /Zi option. 3 is debugEnabled
574 addAttr(rv, "DebugInformationFormat", "3");
575 }
576 Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) {
577 Vector rv = new Vector();
578
579 getBaseCompilerFlags_common(defines,includes, outDir, rv);
580 // Set /Yu option. 3 is pchUseUsingSpecific
581 // Note: Starting VC8 pchUseUsingSpecific is 2 !!!
582 addAttr(rv, "UsePrecompiledHeader", "3");
583 // Set /EHsc- option
584 addAttr(rv, "ExceptionHandling", "FALSE");
585
586 return rv;
587 }
588
589 Vector getBaseLinkerFlags(String outDir, String outDll) {
590 Vector rv = new Vector();
591
592 addAttr(rv, "Name", "VCLinkerTool");
593 addAttr(rv, "AdditionalOptions",
594 "/export:JNI_GetDefaultJavaVMInitArgs " +
595 "/export:JNI_CreateJavaVM " +
596 "/export:JVM_FindClassFromBootLoader "+
597 "/export:JNI_GetCreatedJavaVMs "+
598 "/export:jio_snprintf /export:jio_printf "+
599 "/export:jio_fprintf /export:jio_vfprintf "+
600 "/export:jio_vsnprintf "+
601 "/export:JVM_GetVersionInfo "+
602 "/export:JVM_GetThreadStateNames "+
603 "/export:JVM_GetThreadStateValues "+
604 "/export:JVM_InitAgentProperties ");
605 addAttr(rv, "AdditionalDependencies", "Wsock32.lib winmm.lib");
606 addAttr(rv, "OutputFile", outDll);
607 // Set /INCREMENTAL option. 1 is linkIncrementalNo
608 addAttr(rv, "LinkIncremental", "1");
609 addAttr(rv, "SuppressStartupBanner", "TRUE");
610 addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def");
611 addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"jvm.pdb");
612 // Set /SUBSYSTEM option. 2 is subSystemWindows
613 addAttr(rv, "SubSystem", "2");
614 addAttr(rv, "BaseAddress", "0x8000000");
615 addAttr(rv, "ImportLibrary", outDir+Util.sep+"jvm.lib");
616 // Set /MACHINE option. 1 is machineX86
617 addAttr(rv, "TargetMachine", Util.os().equals("Win32") ? "1" : "17");
618
619 return rv;
620 }
621
622 void getDebugCompilerFlags_common(String opt,Vector rv) {
623
624 // Set /On option
625 addAttr(rv, "Optimization", opt);
626 // Set /FR option. 1 is brAllInfo
627 addAttr(rv, "BrowseInformation", "1");
628 addAttr(rv, "BrowseInformationFile", "$(IntDir)" + Util.sep);
629 // Set /MD option. 2 is rtMultiThreadedDLL
630 addAttr(rv, "RuntimeLibrary", "2");
631 // Set /Oy- option
632 addAttr(rv, "OmitFramePointers", "FALSE");
633
634 }
635
636 Vector getDebugCompilerFlags(String opt) {
637 Vector rv = new Vector();
638
639 getDebugCompilerFlags_common(opt,rv);
640
641 return rv;
642 }
643
644 Vector getDebugLinkerFlags() {
645 Vector rv = new Vector();
646
647 addAttr(rv, "GenerateDebugInformation", "TRUE"); // == /DEBUG option
648
649 return rv;
650 }
651
652 void getAdditionalNonKernelLinkerFlags(Vector rv) {
653 extAttr(rv, "AdditionalOptions",
654 "/export:AsyncGetCallTrace ");
655 }
656
657 void getProductCompilerFlags_common(Vector rv) {
658 // Set /O2 option. 2 is optimizeMaxSpeed
659 addAttr(rv, "Optimization", "2");
660 // Set /Oy- option
661 addAttr(rv, "OmitFramePointers", "FALSE");
662 }
663
664 Vector getProductCompilerFlags() {
665 Vector rv = new Vector();
666
667 getProductCompilerFlags_common(rv);
668 // Set /Ob option. 1 is expandOnlyInline
669 addAttr(rv, "InlineFunctionExpansion", "1");
670 // Set /GF option.
671 addAttr(rv, "StringPooling", "TRUE");
672 // Set /MD option. 2 is rtMultiThreadedDLL
673 addAttr(rv, "RuntimeLibrary", "2");
674 // Set /Gy option
675 addAttr(rv, "EnableFunctionLevelLinking", "TRUE");
676
677 return rv;
678 }
679
680 Vector getProductLinkerFlags() {
681 Vector rv = new Vector();
682
683 // Set /OPT:REF option. 2 is optReferences
684 addAttr(rv, "OptimizeReferences", "2");
685 // Set /OPT:optFolding option. 2 is optFolding
686 addAttr(rv, "EnableCOMDATFolding", "2");
687
688 return rv;
689 }
690
691 String getOptFlag() {
692 return "2";
693 }
694
695 String getNoOptFlag() {
696 return "0";
697 }
698
699 String makeCfgName(String flavourBuild) {
700 return flavourBuild + "|" + Util.os();
701 }
702 }