Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/sourcetools/com.ibm.uma/com/ibm/uma/UMA.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 2018 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
package com.ibm.uma;
23
import java.io.File;
24
import java.io.IOException;
25
import java.io.StringWriter;
26
import java.util.HashMap;
27
import java.util.HashSet;
28
import java.util.Hashtable;
29
import java.util.LinkedHashSet;
30
import java.util.Map;
31
import java.util.Vector;
32
33
import com.ibm.uma.freemarker.TemplateLoader;
34
import com.ibm.uma.om.Artifact;
35
import com.ibm.uma.om.Command;
36
import com.ibm.uma.om.Dependency;
37
import com.ibm.uma.om.Include;
38
import com.ibm.uma.om.Library;
39
import com.ibm.uma.om.MakefileStub;
40
import com.ibm.uma.om.Module;
41
import com.ibm.uma.om.Object;
42
import com.ibm.uma.om.Objects;
43
import com.ibm.uma.om.SubdirArtifact;
44
import com.ibm.uma.om.VPath;
45
import com.ibm.uma.om.parser.Parser;
46
import com.ibm.uma.util.FileAssistant;
47
import com.ibm.uma.util.Logger;
48
49
import freemarker.template.Configuration;
50
import freemarker.template.DefaultObjectWrapper;
51
import freemarker.template.Template;
52
import freemarker.template.TemplateException;
53
import freemarker.template.TemplateModel;
54
55
public class UMA {
56
57
public static final String UMA_TARGETS_IN_TREE = "UMA_TARGETS_IN_TREE";
58
public static final String UMA_TARGETS_IN_TREE_VAR = "$("+UMA_TARGETS_IN_TREE+")";
59
public static final String UMA_PATH_TO_ROOT = "UMA_PATH_TO_ROOT";
60
public static final String UMA_PATH_TO_ROOT_VAR = "$("+UMA_PATH_TO_ROOT+")";
61
public static final String OMR_DIR = "OMR_DIR";
62
public static final String OMR_DIR_VAR = "$("+OMR_DIR+")";
63
public static final String UMA_TARGET_MAKEFILE = "targets.mk";
64
public static final String UMA_MAKELIB_DIR = "makelib";
65
public static final String UMA_MACROS_FILE = "uma_macros.mk";
66
public static final String UMA_MACROS_PATH_FROM_ROOT = UMA_MAKELIB_DIR + "/" + UMA_MACROS_FILE;
67
public static final String UMA_TARGET_MAKEFILE_WITH_PATH = UMA_MAKELIB_DIR + "/" + UMA_TARGET_MAKEFILE;
68
public static final String UMA_MKCONSTANTS_FILE = "mkconstants.mk";
69
public static final String UMA_MKCONSTANTS_PATH_FROM_ROOT = UMA_MAKELIB_DIR + "/" + UMA_MKCONSTANTS_FILE;
70
public static final String UMA_ARTIFACT_CFLAGS_LABEL = "A_CFLAGS";
71
public static final String UMA_ARTIFACT_CXXFLAGS_LABEL = "A_CXXFLAGS";
72
public static final String UMA_ARTIFACT_CPPFLAGS_LABEL = "A_CPPFLAGS";
73
public static final String UMA_ARTIFACT_ASFLAGS_LABEL = "A_ASFLAGS";
74
75
public static final String FREEMARKER_UMA = "uma";
76
77
78
public static final int NUM_OBJECTS_PER_LINE=10;
79
80
static UMA uma;
81
82
public static UMA getUma() {
83
return uma;
84
}
85
86
public IPlatform getPlatform() {
87
return platform;
88
}
89
90
IPlatform platform;
91
IConfiguration configuration;
92
Configuration freemarkerConfig;
93
ISinglePredicateEvaluator singlePredicateEvaluator;
94
Vector<Module> modules;
95
Hashtable<String, Artifact> artifactMap = new Hashtable<String,Artifact>();
96
Hashtable<String, Artifact> artifactLocationMap = new Hashtable<String, Artifact>();
97
String rootDirectory;
98
TemplateLoader templateLoader;
99
String phasePrefix;
100
101
static final String UMA_MAKEFILE_PHASE_PREFIX = "makefile_phase_prefix";
102
103
public UMA(IConfiguration configuration, ISinglePredicateEvaluator singlePredicateEvaluator, String rootDir) throws UMAException {
104
this.configuration = configuration;
105
this.platform = configuration.getPlatform();
106
this.singlePredicateEvaluator = singlePredicateEvaluator;
107
this.rootDirectory = rootDir;
108
if ( !rootDir.endsWith(File.separator) ) this.rootDirectory += File.separator;
109
110
// ensure that the root directory exists before proceeding.
111
File file = new File(this.rootDirectory);
112
if ( !file.exists() ) {
113
throw new UMAException("Error: Source directory " + file.getAbsolutePath() + " does not exist.");
114
}
115
116
UMA.uma = this;
117
118
phasePrefix = configuration.replaceMacro(UMA_MAKEFILE_PHASE_PREFIX);
119
if ( phasePrefix == null ) {
120
phasePrefix = "";
121
} else {
122
phasePrefix += " ";
123
}
124
125
126
// Initialize the Freemarker configuration
127
freemarkerConfig = new Configuration();
128
// Specify how templates will see the data model.
129
freemarkerConfig.setObjectWrapper(new DefaultObjectWrapper());
130
this.templateLoader = new TemplateLoader();
131
freemarkerConfig.setTemplateLoader(this.templateLoader);
132
}
133
134
public IConfiguration getConfiguration() {
135
return configuration;
136
}
137
138
public ISinglePredicateEvaluator getSinglePredicateEvaluator() {
139
return singlePredicateEvaluator;
140
}
141
142
public Vector<Module> getModules() {
143
return modules;
144
}
145
146
public void addArtifact( Artifact artifact ) throws UMAException {
147
String artifactKey = artifact.getArtifactKey();
148
Artifact artifactInMap = artifactMap.get(artifactKey);
149
if ( artifactInMap != null ) {
150
throw new DuplicateArtifactKeyException("Duplicate artifact key found [" + artifactKey + "] in file " + artifact.getContainingFile() + " already found in file " + artifactInMap.getContainingFile() );
151
}
152
artifactMap.put(artifactKey, artifact);
153
}
154
155
public void validateArtifactLocations() throws DuplicateArtifactKeyException, UMAException {
156
157
// Artifacts won't know if they are in bundles until all artifacts are created
158
for (Artifact artifact : getArtifacts().values()) {
159
if ( artifact.evaluate() ) {
160
String artifactLocationKey = platform.getLibOnDiskName(artifact);
161
Artifact artifactLocationInMap = artifactLocationMap.get(artifactLocationKey);
162
if ( artifactLocationInMap != null ) {
163
throw new DuplicateArtifactKeyException("Duplicate artifact locations found [" + artifactLocationKey + "] in file " + artifact.getContainingFile() + " already found in file " + artifactLocationInMap.getContainingFile() );
164
}
165
artifactLocationMap.put(artifactLocationKey, artifact);
166
}
167
}
168
}
169
170
public Artifact getArtifact(String artifactName) {
171
return artifactMap.get(artifactName);
172
}
173
174
public Artifact getBundleArtifact(String artifactName) throws UMAException {
175
for (Artifact artifact : artifactMap.values()) {
176
if (artifact.isBundle()) {
177
if (artifact.getTargetName().equals(artifactName)) {
178
return artifact;
179
}
180
}
181
}
182
return null;
183
}
184
185
public Hashtable<String, Artifact> getArtifacts() {
186
return artifactMap;
187
}
188
189
190
191
public String getRootDirectory() {
192
return rootDirectory;
193
}
194
195
public void generate() throws UMAException {
196
197
Parser parser = new Parser(this);
198
if ( !parser.parse() ) {
199
return;
200
}
201
202
modules = parser.getModules();
203
204
platform.decorateModules(modules);
205
206
// Freemarker invocation
207
208
try {
209
Map<String, TemplateModel> map = new HashMap<String, TemplateModel>();
210
map.put(FREEMARKER_UMA, new com.ibm.uma.freemarker.UMA());
211
for ( String tmp : templateLoader.getTemplates() ) {
212
Template template = freemarkerConfig.getTemplate(tmp);
213
String filename = tmp.substring(0, tmp.lastIndexOf(".ftl"));
214
StringWriter writer = new StringWriter();
215
template.process(map, writer);
216
new FileAssistant(this.rootDirectory+filename, writer.getBuffer()).writeToDisk();
217
}
218
} catch (IOException e) {
219
throw new UMAException(e);
220
221
} catch (TemplateException e) {
222
throw new UMAException(e);
223
}
224
225
writeTargetInformationMacrosFile();
226
227
// top level module is the first in the list.
228
Module rootModule = null;
229
for ( Module module : modules ) {
230
if ( module.isTopLevel() ) {
231
if ( rootModule != null ) {
232
throw new UMAException("Error: more than one root module " + rootModule.getFullName() + " and " + module.getFullName());
233
}
234
rootModule = module;
235
}
236
}
237
if ( rootModule == null ) {
238
throw new UMAException("Error: no " + configuration.getMetadataFilename() + " found in the root directory " + getRootDirectory());
239
}
240
writeDirectoryMakefile(rootModule);
241
242
Logger.getLogger().println(Logger.InformationL1Log, "Complete");
243
}
244
245
class LineWrapMakefileDirective {
246
int itemCount = 0;
247
int maxItems = NUM_OBJECTS_PER_LINE;
248
String underMaxSeperator = " ";
249
String overMaxSeperator = "\\\n ";
250
StringBuffer stringBuffer;
251
252
LineWrapMakefileDirective(StringBuffer stringBuffer) {
253
this.stringBuffer = stringBuffer;
254
}
255
256
LineWrapMakefileDirective(StringBuffer stringBuffer, String underMaxSeperator, String overMaxSeperator) {
257
this.stringBuffer = stringBuffer;
258
this.underMaxSeperator = underMaxSeperator;
259
this.overMaxSeperator = overMaxSeperator;
260
}
261
262
void addItem(String item) {
263
if (itemCount<maxItems) {
264
itemCount++;
265
stringBuffer.append(underMaxSeperator);
266
} else {
267
itemCount = 1;
268
stringBuffer.append(overMaxSeperator);
269
}
270
stringBuffer.append(item);
271
}
272
}
273
274
// This function takes a module and creates a makefile for the directory,
275
// then recursively calls this function on all sub-modules.
276
void writeDirectoryMakefile(Module module) throws UMAException {
277
if ( !module.evaluate() ) return;
278
279
String modulePath = new File(module.getModulePath()).getParent();
280
Logger.getLogger().println(Logger.InformationL2Log, "Producing makefile(s) for " + modulePath );
281
282
for ( Artifact artifact : module.getArtifacts() ) {
283
writeMakefileForArtifact(artifact);
284
}
285
286
if ( module.requiresDispatchMakefile() ) {
287
// There needs to be a dispatch makefile
288
String makefileName = modulePath + File.separator +"makefile";
289
StringBuffer buffer = new StringBuffer();
290
FileAssistant fa = new FileAssistant(makefileName, buffer);
291
buffer.append(configuration.getMakefileCopyrightNotice());
292
String pathToRoot = determinePathToRoot(module);
293
294
295
Vector<String> targets = new Vector<String>();
296
Vector<String> specialTargets = new Vector<String>();
297
for ( Artifact artifact : module.getAllArtifactsInTree() ) {
298
if ( !artifact.evaluate() ) continue;
299
if ( artifact.getType() == Artifact.TYPE_TARGET ) {
300
if ( artifact.includeInAllTarget() ) {
301
/*
302
* The separation of targets into targets and specialTargets
303
* is being done to allow the 'TARGET' type artifacts to be built first.
304
* This is a weak way of saying that the whole system is dependent on
305
* these targets without having to add the dependency to each and every
306
* artifact.
307
*
308
* This only works when not using -j on gmake and because
309
* gmake will do the targets in the order they are on the dependency line.
310
*
311
*/
312
specialTargets.add(artifact.getMakefileName());
313
}
314
} else {
315
if (artifact.includeInAllTarget()) {
316
targets.add(artifact.getMakefileName());
317
}
318
}
319
}
320
321
buffer.append(UMA_PATH_TO_ROOT+"=" + pathToRoot + "\n");
322
buffer.append(OMR_DIR+"?=" + pathToRoot + "omr\n");
323
StringBuffer targetsInTreeBuffer = new StringBuffer();
324
LineWrapMakefileDirective lwmd = new LineWrapMakefileDirective(targetsInTreeBuffer);
325
targetsInTreeBuffer.append(UMA_TARGETS_IN_TREE+"=");
326
for ( String target : specialTargets ) {
327
lwmd.addItem(target);
328
}
329
for ( String target : targets ) {
330
lwmd.addItem(target);
331
}
332
buffer.append(targetsInTreeBuffer.toString());
333
334
buffer.append("\n\ninclude " + UMA_PATH_TO_ROOT_VAR + UMA_MKCONSTANTS_PATH_FROM_ROOT + "\n");
335
buffer.append("include " + UMA_PATH_TO_ROOT_VAR + UMA_MACROS_PATH_FROM_ROOT + "\n\n");
336
337
buffer.append(phasePrefix + "all: " + UMA_TARGETS_IN_TREE_VAR + "\n\n");
338
339
buffer.append("clean: $(addprefix clean_," + UMA_TARGETS_IN_TREE_VAR + ")\n\n");
340
341
buffer.append("ddrgen: $(addprefix ddrgen_," + UMA_TARGETS_IN_TREE_VAR + ")\n\n");
342
343
buffer.append(
344
"static: UMA_STATIC_BUILD=1\n" +
345
" export UMA_STATIC_BUILD\n\n" +
346
"static:\n" +
347
" $(MAKE) -f makefile\n\n\n");
348
349
350
for ( int phase=0; phase<configuration.numberOfPhases(); phase++ ) {
351
Vector<String> phaseTargets = new Vector<String>();
352
Vector<String> specialPhaseTargets = new Vector<String>();
353
for ( Artifact artifact : module.getAllArtifactsInTree() ) {
354
if ( !artifact.evaluate() ) continue;
355
if ( !artifact.isInPhase(phase) ) continue;
356
if ( artifact.getType() == Artifact.TYPE_TARGET ) {
357
/*
358
* The separation of targets into phaseTargets and specialPhaseTargets
359
* is being done to allow the 'TARGET' type artifacts to be built first.
360
* This is a weak way of saying that the whole system is dependent on
361
* these targets without having to add the dependency to each and every
362
* artifact.
363
*
364
* This only works when not using -j on gmake and because
365
* gmake will do the targets in the order they are on the dependency line.
366
*
367
*/
368
specialPhaseTargets.add(artifact.getMakefileName());
369
} else {
370
phaseTargets.add(artifact.getMakefileName());
371
}
372
}
373
374
buffer.append(phasePrefix + "phase_" + configuration.phaseName(phase) + ":");
375
StringBuffer targetsInPhaseBuffer = new StringBuffer();
376
lwmd = new LineWrapMakefileDirective(targetsInPhaseBuffer);
377
for ( String target : specialPhaseTargets ) {
378
lwmd.addItem(target);
379
}
380
for ( String target : phaseTargets ) {
381
lwmd.addItem(target);
382
}
383
buffer.append( targetsInPhaseBuffer.toString() + "\n" );
384
}
385
386
buffer.append( "\n" );
387
388
for ( Artifact artifact : module.getAllArtifactsInTree() ) {
389
if ( !artifact.evaluate() ) continue;
390
switch (artifact.getType()) {
391
case Artifact.TYPE_SUBDIR:
392
// Ignore this type of artifact. It is only used
393
// to glue the tree together.
394
break;
395
case Artifact.TYPE_TARGET:
396
buffer.append( "clean_" + artifact.getMakefileName() + ":\n" );
397
for ( Command command : artifact.getCommands() ) {
398
if ( !command.evaluate() || command.getType() != Command.TYPE_CLEAN ) continue;
399
buffer.append("\t" + command.getCommand() + "\n");
400
}
401
buffer.append( "\n" );
402
403
buffer.append( "ddrgen_" + artifact.getMakefileName() + ":\n" );
404
for ( Command command : artifact.getCommands() ) {
405
if ( !command.evaluate() || command.getType() != Command.TYPE_DDRGEN ) continue;
406
buffer.append("\t" + command.getCommand() + "\n");
407
}
408
buffer.append( "\n" );
409
410
buffer.append( artifact.getMakefileName() + ":" );
411
for ( Dependency dependency : artifact.getDependendies() ) {
412
if ( !dependency.evaluate() ) continue;
413
buffer.append( " " + dependency.getDependency() );
414
}
415
buffer.append( "\n" );
416
for ( Command command : artifact.getCommands() ) {
417
if ( !command.evaluate() || command.getType() != Command.TYPE_ALL ) continue;
418
buffer.append("\t" + command.getCommand() + "\n");
419
}
420
buffer.append( "\n" );
421
break;
422
default:
423
buffer.append( "clean_" + artifact.getMakefileName() + ":\n\t$(" + artifact.getMakefileName() + "_build) clean\n\n");
424
buffer.append( "ddrgen_" + artifact.getMakefileName() + ":\n\t$(" + artifact.getMakefileName() + "_build) ddrgen\n\n");
425
buffer.append( artifact.getMakefileName() + ": $(" + artifact.getMakefileName() + "_dependencies)\n\t$(" + artifact.getMakefileName() + "_build)\n\n");
426
break;
427
}
428
}
429
430
if ( module.isTopLevel() ) {
431
platform.writeTopLevelTargets(buffer);
432
}
433
434
buffer.append(".PHONY: all clean ddrgen");
435
StringBuffer phonyTargetsBuffer = new StringBuffer();
436
lwmd = new LineWrapMakefileDirective(phonyTargetsBuffer);
437
for ( String phonyTarget : specialTargets ) {
438
lwmd.addItem(phonyTarget);
439
lwmd.addItem(" clean_" + phonyTarget);
440
}
441
for ( String phonyTarget : targets ) {
442
lwmd.addItem(phonyTarget);
443
lwmd.addItem(" clean_" + phonyTarget);
444
}
445
buffer.append(phonyTargetsBuffer.toString()+"\n");
446
fa.writeToDisk();
447
448
}
449
450
for ( Artifact artifact : module.getArtifacts() ) {
451
if ( artifact.getType() == Artifact.TYPE_SUBDIR ) {
452
SubdirArtifact subdirArtifact = (SubdirArtifact) artifact;
453
writeDirectoryMakefile(subdirArtifact.getSubdirModule());
454
}
455
}
456
}
457
458
void addDependencies( Vector<Library> libraries, Hashtable<String, LinkedHashSet<String>> buildDependencies, Artifact artifact ) throws UMAException {
459
String target = artifact.getMakefileName();
460
LinkedHashSet<String> deps = buildDependencies.get(target);
461
if ( deps == null ) {
462
deps = new LinkedHashSet<String>();
463
buildDependencies.put(target, deps);
464
}
465
for ( Library library : libraries ) {
466
if ( library.evaluate() ) {
467
if ( library.getType() != Library.TYPE_BUILD ) continue;
468
Artifact libArtifact = getArtifact(library.getName());
469
if ( libArtifact == null ) continue;
470
String libName = libArtifact.getMakefileName();
471
if ( libArtifact.isInBundle() ) {
472
Artifact bundle = getBundleArtifact(libArtifact.getBundle());
473
if (artifact != bundle) {
474
/* If we are not dealing with the bundle itself, then substitute the
475
* bundle name for the library. */
476
libName = bundle.getMakefileName();
477
}
478
}
479
if ( !deps.contains(libName) && !libName.equalsIgnoreCase(target)) {
480
deps.add(libName);
481
}
482
}
483
}
484
for ( Dependency artifactDependency : artifact.getDependendies() ) {
485
if ( artifactDependency.evaluate() ) {
486
String dependency = artifactDependency.getDependency();
487
if ( !deps.contains(dependency) && !dependency.equalsIgnoreCase(target)) {
488
deps.add(dependency);
489
}
490
}
491
}
492
}
493
494
void expandLibraryDependencies(Artifact artifact, StringBuffer libLocations) throws UMAException {
495
switch (artifact.getType()) {
496
case Artifact.TYPE_BUNDLE: // FALL-THRU
497
case Artifact.TYPE_STATIC: // FALL-THRU
498
case Artifact.TYPE_SHARED:
499
libLocations.append(artifact.getTargetNameWithScope() + "_deps=" + artifact.getTargetName());
500
Hashtable<String, Library> libs = artifact.getAllLibrariesThisArtifactDependsOn();
501
for ( Library lib : libs.values() ) {
502
if ( lib.evaluate() ) {
503
switch ( lib.getType() ) {
504
case Library.TYPE_MACRO:
505
String mlibs = platform.replaceMacro(lib.getName());
506
if (mlibs != null) {
507
libLocations.append(" " + mlibs);
508
}
509
continue;
510
}
511
libLocations.append(" " + lib.getName());
512
}
513
}
514
515
/* for bundles emit a dependency on element in the bundle */
516
if (artifact.getType() == Artifact.TYPE_BUNDLE) {
517
String bundleName = artifact.getTargetName();
518
for (Artifact artifactCursor : artifactMap.values()) {
519
if (!artifactCursor.evaluate()) {
520
continue;
521
}
522
if (!artifactCursor.isInBundle()) {
523
continue;
524
}
525
if (!artifactCursor.getBundle().equalsIgnoreCase(bundleName)) {
526
continue;
527
}
528
libLocations.append(" " + artifactCursor.getArtifactKey());
529
}
530
}
531
libLocations.append("\n\n");
532
break;
533
}
534
}
535
536
537
538
void writeTargetInformationMacrosFile() throws UMAException {
539
/*
540
* Buffer for information about which libraries are static vs. shared
541
* and their locations on disk and references on the target and link lines.
542
*/
543
StringBuffer libLocations = new StringBuffer();
544
/*
545
* Buffer for target rules.
546
*/
547
StringBuffer targetRules = new StringBuffer();
548
549
/*
550
* A couple of hashtable to gather information an artifacts build dependencies.
551
*/
552
Hashtable<String, LinkedHashSet<String>> buildDependencies = new Hashtable<String,LinkedHashSet<String>>();
553
Hashtable<String, LinkedHashSet<String>> staticBuildDependencies = new Hashtable<String,LinkedHashSet<String>>();
554
555
for ( Module module : modules) {
556
if ( !module.evaluate() ) continue;
557
// determine build dependencies
558
for (Artifact artifact : module.getArtifacts()) {
559
if ( !artifact.evaluate() ) continue;
560
switch (artifact.getType()) {
561
case Artifact.TYPE_BUNDLE: // Fall Through
562
case Artifact.TYPE_SHARED:
563
libLocations.append(artifact.getTargetNameWithScope()+"_alllib="+artifact.getTargetName()+"\n");
564
libLocations.append(artifact.getTargetNameWithScope()+"_sharedlib="+artifact.getTargetName()+"\n");
565
platform.addLibraryLocationInformation(artifact, libLocations);
566
expandLibraryDependencies(artifact, libLocations);
567
break;
568
case Artifact.TYPE_STATIC:
569
libLocations.append(artifact.getTargetNameWithScope()+"_alllib="+artifact.getTargetName()+"\n");
570
libLocations.append(artifact.getTargetNameWithScope()+"_staticlib="+artifact.getTargetName()+"\n");
571
platform.addLibraryLocationInformation(artifact, libLocations);
572
expandLibraryDependencies(artifact, libLocations);
573
break;
574
case Artifact.TYPE_EXECUTABLE:
575
break;
576
}
577
578
switch (artifact.getType()) {
579
case Artifact.TYPE_BUNDLE: // Fall Through
580
case Artifact.TYPE_SHARED: // Fall Through
581
case Artifact.TYPE_STATIC: // Fall Through
582
case Artifact.TYPE_EXECUTABLE: // Fall Through
583
targetRules.append(
584
artifact.getMakefileName() + "_build" + "=+$(MAKE) $(UMA_WINDOWS_PARRALLEL_HACK) -C " + UMA_PATH_TO_ROOT_VAR + artifact.getContainingModule().getFullName() + " -f " + artifact.getMakefileFileName() + "\n");
585
break;
586
}
587
588
addDependencies( artifact.getLibraries(), buildDependencies, artifact);
589
addDependencies( artifact.getStaticLinkLibraries(), staticBuildDependencies, artifact);
590
}
591
}
592
593
/*
594
* Write uma macros helper makefile. This file contains several variable definitions that allow
595
* easy reference to information about the artifacts. e.g.,
596
*/
597
File makelibDirectory = new File(UMA.getUma().getRootDirectory() + UMA_MAKELIB_DIR);
598
makelibDirectory.mkdir();
599
FileAssistant fa = new FileAssistant(UMA.getUma().getRootDirectory() + UMA_MACROS_PATH_FROM_ROOT );
600
StringBuffer buffer = fa.getStringBuffer();
601
buffer.append("# UMA Macro Helper Definition Makefile\n" );
602
buffer.append(configuration.getMakefileCopyrightNotice());
603
buffer.append(libLocations.toString()+"\n\n\n");
604
605
for (String target : buildDependencies.keySet()) {
606
buffer.append( "\n");
607
for ( String dependency : buildDependencies.get(target) ) {
608
buffer.append(target + "_dependencies+=$(findstring " + dependency + ","+ UMA_TARGETS_IN_TREE_VAR +")\n");
609
}
610
buffer.append("\n");
611
}
612
buffer.append("\n\nifdef UMA_STATIC_BUILD\n\n");
613
for (String target : staticBuildDependencies.keySet()) {
614
buffer.append( "\n");
615
for ( String dependency : staticBuildDependencies.get(target) ) {
616
buffer.append(target + "_dependencies+=$(findstring " + dependency + ","+ UMA_TARGETS_IN_TREE_VAR +")\n");
617
}
618
buffer.append("\n");
619
}
620
buffer.append("\n\nendif\n\n");
621
622
buffer.append( targetRules.toString() );
623
624
fa.writeToDisk();
625
}
626
627
void writeMakefileForArtifact(Artifact artifact) throws UMAException {
628
if ( !artifact.evaluate() ||
629
artifact.getType() == Artifact.TYPE_SUBDIR ||
630
artifact.getType() == Artifact.TYPE_REFERENCE ||
631
artifact.getType() == Artifact.TYPE_TARGET) return;
632
633
Module module = artifact.getContainingModule();
634
String modulePath = new File(module.getModulePath()).getParent();
635
String makefileName = artifact.getMakefileFileName();
636
makefileName = modulePath + File.separator + makefileName;
637
638
platform.writePlatformSpecificFiles(artifact);
639
640
FileAssistant fa = new FileAssistant(makefileName);
641
StringBuffer buffer = fa.getStringBuffer();
642
buffer.append("# Makefile for '" + artifact.getMakefileName() + "'\n" );
643
buffer.append(configuration.getMakefileCopyrightNotice());
644
String pathToRoot = determinePathToRoot(module);
645
buffer.append(UMA_PATH_TO_ROOT+"=" + pathToRoot + "\n");
646
buffer.append(OMR_DIR+"?=" + pathToRoot + "omr\n");
647
switch ( artifact.getType() ) {
648
case Artifact.TYPE_BUNDLE: // fall-thru
649
case Artifact.TYPE_SHARED:
650
buffer.append("UMA_TARGET_TYPE=DLL\n");
651
break;
652
case Artifact.TYPE_EXECUTABLE:
653
buffer.append("UMA_TARGET_TYPE=EXE\n");
654
break;
655
case Artifact.TYPE_STATIC:
656
buffer.append("UMA_TARGET_TYPE=LIB\n");
657
break;
658
}
659
buffer.append("UMA_TARGET_NAME=" + artifact.getTargetNameWithScope() + "\n");
660
661
/* On OSX, <LIB_NAME_DYLIB>.dylib should match the -install_name <LIB_NAME_INSTALL>.
662
* Otherwise, the linker is unable to find the required library. Currently, LIB_NAME_DYLIB
663
* doesn't match LIB_NAME_INSTALL. LIB_NAME_DYLIB has major and minor build versions
664
* appended whereas LIB_NAME_INSTALL doesn't contain version info. UMA_LIB_NAME will contain
665
* LIB_NAME_INSTALL with major and minor build versions.
666
*/
667
buffer.append("UMA_LIB_NAME=" + platform.getTargetNameWithRelease(artifact) + "\n");
668
669
if ( artifact.getTargetPath() != null ) {
670
buffer.append("UMA_TARGET_PATH=" + UMA_PATH_TO_ROOT_VAR + artifact.getTargetPath()+"\n");
671
}
672
if ( artifact.flagSet("isCPlusPlus") ) {
673
buffer.append("UMA_IS_C_PLUS_PLUS=1\n");
674
}
675
platform.addArtifactSpecificMakefileInformation(artifact, buffer);
676
677
buffer.append("\ninclude "+UMA_PATH_TO_ROOT_VAR + UMA_MKCONSTANTS_PATH_FROM_ROOT + "\n\n");
678
writeMakefileIncludeLine(buffer, module, artifact);
679
writeMakefileLibraryLine(buffer, module, artifact);
680
buffer.append(platform.writeMakefileFlagsLine(artifact).toString());
681
writeMakefileObjectLine(buffer, module, artifact);
682
buffer.append(platform.writeMakefileExtras(artifact).toString());
683
writeMakefileStubs(buffer, module, artifact);
684
writeMakefileVPathInformation(buffer, module, artifact);
685
buffer.append(platform.writeMakefilePostscript(artifact).toString());
686
if (artifact.getCommands().isEmpty()) {
687
buffer.append("\ninclude "+UMA_PATH_TO_ROOT_VAR+UMA_TARGET_MAKEFILE_WITH_PATH+"\n");
688
} else {
689
/* Support custom recipes for building a target.
690
*
691
* If module.xml specifies <commands /> for this artifact, we will use the commands
692
* to build the on-disk artifact, instead of the rules in targets.mk.
693
*/
694
695
/* uma_macros.mk defines the names of the ondisk artifact and its dependencies */
696
buffer.append("include " + UMA_PATH_TO_ROOT_VAR + UMA_MACROS_PATH_FROM_ROOT + "\n\n");
697
698
/* Defines the default target.
699
*
700
* $($(target)_ondisk): $($(target)_dependencies)
701
* commands with type="all"
702
*/
703
buffer.append("$(" + artifact.getTargetNameWithScope() + "_ondisk): ");
704
buffer.append("$(" + artifact.getTargetNameWithScope() + "_dependencies)\n");
705
for (Command command : artifact.getCommands()) {
706
if (!command.evaluate() || command.getType() != Command.TYPE_ALL)
707
continue;
708
buffer.append("\t" + command.getCommand() + "\n");
709
}
710
buffer.append("\n");
711
712
/* Defines the clean target.
713
*
714
* clean:
715
* commands with type="clean"
716
*/
717
buffer.append("clean:\n");
718
for (Command command : artifact.getCommands()) {
719
if (!command.evaluate() || command.getType() != Command.TYPE_CLEAN)
720
continue;
721
buffer.append("\t" + command.getCommand() + "\n");
722
}
723
buffer.append("\n");
724
725
/* Defines the ddrgen target.
726
*
727
* ddrgen:
728
* commands with type="ddrgen"
729
*/
730
buffer.append("ddrgen:\n");
731
for (Command command : artifact.getCommands()) {
732
if (!command.evaluate() || command.getType() != Command.TYPE_DDRGEN)
733
continue;
734
buffer.append("\t" + command.getCommand() + "\n");
735
}
736
buffer.append("\n");
737
}
738
fa.writeToDisk();
739
}
740
741
void writeMakefileVPathInformation( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {
742
for ( VPath vpath : artifact.getVPaths() ) {
743
if ( !vpath.evaluate() ) continue;
744
if ( vpath.getPath() == null ) continue;
745
// vpath for a any pattern
746
buffer.append("vpath " + vpath.getPattern() + " ");
747
if ( vpath.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );
748
buffer.append(vpath.getPath() + "\n");
749
if ( vpath.isAugmentObjects() ) {
750
buffer.append("UMA_OBJECTS+=" + vpath.getObjectFile() + "\n");
751
}
752
if ( vpath.isAugmentIncludes() ) {
753
buffer.append("UMA_INCLUDES+=");
754
if ( vpath.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );
755
buffer.append(vpath.getPath() + "\n");
756
}
757
758
}
759
}
760
761
void writeMakefileIncludeLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {
762
Vector<Include> includes = artifact.getIncludes();
763
764
buffer.append("UMA_INCLUDES=. " + configuration.getAdditionalIncludesForArtifact(artifact));
765
766
for ( Include include : includes ) {
767
if (include.evaluate()) {
768
if ( include.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );
769
buffer.append(include.getPath() + " ");
770
}
771
}
772
buffer.append("\n");
773
}
774
775
/**
776
* @param artifact artifact being built
777
* @param type The type of library to find.
778
* @param forStatic Whether these libraries are for an UMA_STATIC_BUILD
779
* @param libArtifact artifact being linked in
780
* @throws UMAException
781
*/
782
private String getLibraryDependenciesOfType( Artifact artifact, int type, boolean forStatic, Artifact libArtifact ) throws UMAException {
783
784
String libName = libArtifact.getTargetNameWithScope();
785
786
if ( type == Library.TYPE_BUILD ) {
787
/* static versions use the library name without any tweaks */
788
if (forStatic) {
789
return libName + " ";
790
}
791
792
/* unbundled artifacts don't require special treatment */
793
if (!libArtifact.isInBundle()) {
794
return libName + " ";
795
}
796
}
797
798
StringBuilder stringBuilder = new StringBuilder();
799
800
/* executables/external DLL's should link in the *actual* code, not the bundle */
801
if (!artifact.isInBundle() && (artifact.getType() == Artifact.TYPE_EXECUTABLE) ) {
802
803
if ( type == Library.TYPE_BUILD ) {
804
stringBuilder.append(libName + " ");
805
}
806
807
for (Library inheritedLib : libArtifact.getLibraries()) {
808
if (!inheritedLib.evaluate()) {
809
continue;
810
}
811
812
Artifact inheritedLibArtifact = getArtifact(inheritedLib.getName());
813
if ( inheritedLib.getType() == Library.TYPE_BUILD) {
814
/* Do not include the library if its artifact is not included */
815
if (null == inheritedLibArtifact || !inheritedLibArtifact.evaluate()) {
816
continue;
817
}
818
}
819
820
if (inheritedLib.getType() == type) {
821
/* macro libraries will have their name mangled */
822
if (type == Library.TYPE_MACRO) {
823
if (null != inheritedLibArtifact && !inheritedLibArtifact.evaluate()) {
824
continue;
825
}
826
String libs = platform.replaceMacro(inheritedLib.getName());
827
if ( libs != null ) {
828
stringBuilder.append(libs + " ");
829
}
830
} else {
831
stringBuilder.append(inheritedLib.getName() + " ");
832
}
833
}
834
835
836
}
837
return stringBuilder.toString();
838
}
839
840
if ( type == Library.TYPE_BUILD ) {
841
/* if we are building the bundle then used unmodified names */
842
Artifact bundle = getBundleArtifact(libArtifact.getBundle());
843
if (bundle == artifact) {
844
return stringBuilder.toString();
845
}
846
847
/* otherwise the library is in a bundle and we should substitute the bundle name (ugh) */
848
stringBuilder.append(bundle.getArtifactKey() + " ");
849
return stringBuilder.toString();
850
}
851
852
return "";
853
}
854
855
/**
856
* @param artifact artifact being built
857
* @param libraries The list of libraries which we are through.
858
* @param type The type of library to find.
859
* @param forStatic Whether these libraries are for an UMA_STATIC_BUILD
860
* @throws UMAException
861
*/
862
String getLibrariesOfType( Artifact artifact, Vector<Library> libraries, int type, boolean forStatic ) throws UMAException {
863
if ( libraries.size() < 1 )
864
return "";
865
866
StringBuilder stringBuilder = new StringBuilder();
867
868
for ( Library library : libraries ) {
869
if ( library.evaluate()) {
870
if ( library.getType() == Library.TYPE_BUILD ) {
871
/* If the library is an artifact, we want to include its dependencies as
872
* well as itself.
873
*/
874
Artifact libArtifact = getArtifact(library.getName());
875
if ( libArtifact != null ) {
876
if ( libArtifact.evaluate() ) {
877
stringBuilder.append(getLibraryDependenciesOfType(artifact, type, forStatic, libArtifact));
878
}
879
} else {
880
Logger.getLogger().println(Logger.WarningLog, "Warning: unknown library reference " + library.getName() + " in: " + artifact.getContainingFile());
881
}
882
} else if (library.getType() == type) {
883
/* macro libraries will have their name mangled */
884
if (type == Library.TYPE_MACRO) {
885
String libs = platform.replaceMacro(library.getName());
886
if ( libs != null ) {
887
stringBuilder.append(libs + " ");
888
}
889
} else {
890
stringBuilder.append(library.getName() + " ");
891
}
892
}
893
}
894
}
895
return stringBuilder.toString();
896
}
897
898
void writeMakefileLibraryLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {
899
if ( artifact.getType() != Artifact.TYPE_BUNDLE && artifact.getType() != Artifact.TYPE_SHARED && artifact.getType() != Artifact.TYPE_EXECUTABLE) return;
900
Vector<Library> libraries = artifact.getLibraries();
901
902
String libs = getLibrariesOfType(artifact, libraries, Library.TYPE_BUILD, false);
903
libs = libs + getLibrariesOfType(artifact, libraries, Library.TYPE_SYSTEM, false);
904
libs = libs + getLibrariesOfType(artifact, libraries, Library.TYPE_MACRO, false);
905
if (libs.length() != 0) {
906
buffer.append("UMA_LIBRARIES := " + libs + "\n");
907
}
908
909
libs = getLibrariesOfType(artifact, libraries, Library.TYPE_EXTERNAL, false);
910
if (libs.length() != 0) {
911
buffer.append("UMA_EXTERNAL_LIBRARIES := " + libs + "\n");
912
}
913
914
/* Static libraries will have their dependencies compiled in */
915
libraries = artifact.getStaticLinkLibraries();
916
libs = getLibrariesOfType(artifact, libraries, Library.TYPE_BUILD, true);
917
if (libs.length() != 0) {
918
buffer.append("UMA_STATIC_LIBRARIES := " + libs + "\n");
919
}
920
}
921
922
void writeMakefileObjectLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {
923
// Add all objects into a set, eliminating duplicates.
924
HashSet<String> objtable = new HashSet<String>();
925
Vector<Object> objects = artifact.getObjects();
926
for ( Object object : objects ) {
927
if ( object.evaluate() ) {
928
switch (object.getType()) {
929
case Object.SINGLE:
930
if ( !objtable.contains(object.getName()) ) {
931
objtable.add(object.getName());
932
}
933
break;
934
case Object.GROUP:
935
Vector<String> newGroups = new Vector<String>();
936
newGroups.add(object.getName());
937
while ( newGroups != null ) {
938
Vector<String> groups = newGroups;
939
newGroups = null;
940
for ( String groupName : groups ) {
941
Objects objs = module.getObjects().get(groupName);
942
if ( objs == null ) {
943
throw new UMAException("Error: bad object group name [" +groupName+"] in " + module.getModulePath() +"." );
944
}
945
if ( objs.evaluate() ) {
946
for ( Object obj : objs.getObjects()) {
947
if ( obj.evaluate() ) {
948
switch (obj.getType()) {
949
case Object.SINGLE:
950
if ( !objtable.contains(obj.getName()) ) {
951
objtable.add(obj.getName());
952
}
953
break;
954
case Object.GROUP:
955
if ( newGroups == null ) {
956
newGroups = new Vector<String>();
957
}
958
newGroups.add(obj.getName());
959
break;
960
}
961
}
962
}
963
}
964
}
965
}
966
break;
967
} // switch
968
}
969
}
970
971
StringBuffer objectBuffer = new StringBuffer();
972
if ( objtable.size() >= 1 ) {
973
produceObjectLine(objectBuffer, objtable, "UMA_OBJECTS");
974
}
975
HashSet<String> targetSpecificObjects = new HashSet<String>();
976
produceObjectLine(objectBuffer, targetSpecificObjects, "UMA_OBJECTS+");
977
978
objtable = new HashSet<String>();
979
platform.addTargetSpecificObjectsForStaticLink(objtable, artifact);
980
if ( objtable.size() >= 1) {
981
produceObjectLine(objectBuffer, objtable, "UMA_STATIC_OBJECTS");
982
}
983
if ( objectBuffer.length() > 0 ) {
984
buffer.append(objectBuffer.toString());
985
}
986
}
987
988
void produceObjectLine( StringBuffer objectBuffer, HashSet<String> objtable, String tag) {
989
objectBuffer.append(tag + "=");
990
int objectsWritten = 0;
991
for ( String obj : objtable ) {
992
objectBuffer.append(" " + obj);
993
objectsWritten ++;
994
if ( objectsWritten % UMA.NUM_OBJECTS_PER_LINE == 0 ) {
995
objectBuffer.append("\\\n");
996
}
997
}
998
objectBuffer.append("\n");
999
}
1000
1001
void writeMakefileStubs( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {
1002
Vector<MakefileStub> makefileStubs = artifact.getMakefileStubs();
1003
if ( !artifact.appendRelease() ) {
1004
buffer.append("UMA_DO_NOT_APPEND_RELEASE_TO_DLL=1\n");
1005
}
1006
for ( MakefileStub stub : makefileStubs ) {
1007
if ( stub.evaluate() ) {
1008
String[] stubs = stub.toString().split("\\\\n");
1009
for (int k=0; k<stubs.length; k++) {
1010
buffer.append(stubs[k] + "\n");
1011
}
1012
}
1013
}
1014
}
1015
1016
String determinePathToRoot( Module module ) {
1017
String pathToRoot = "";
1018
int depth = module.getModuleDepth();
1019
for ( int i=0; i<depth; i++ ) {
1020
pathToRoot = pathToRoot + "../";
1021
}
1022
if (pathToRoot.equals("")) return "./";
1023
return pathToRoot;
1024
}
1025
}
1026
1027