Path: blob/master/sourcetools/com.ibm.uma/com/ibm/uma/UMA.java
6004 views
/*******************************************************************************1* Copyright (c) 2001, 2018 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/21package com.ibm.uma;22import java.io.File;23import java.io.IOException;24import java.io.StringWriter;25import java.util.HashMap;26import java.util.HashSet;27import java.util.Hashtable;28import java.util.LinkedHashSet;29import java.util.Map;30import java.util.Vector;3132import com.ibm.uma.freemarker.TemplateLoader;33import com.ibm.uma.om.Artifact;34import com.ibm.uma.om.Command;35import com.ibm.uma.om.Dependency;36import com.ibm.uma.om.Include;37import com.ibm.uma.om.Library;38import com.ibm.uma.om.MakefileStub;39import com.ibm.uma.om.Module;40import com.ibm.uma.om.Object;41import com.ibm.uma.om.Objects;42import com.ibm.uma.om.SubdirArtifact;43import com.ibm.uma.om.VPath;44import com.ibm.uma.om.parser.Parser;45import com.ibm.uma.util.FileAssistant;46import com.ibm.uma.util.Logger;4748import freemarker.template.Configuration;49import freemarker.template.DefaultObjectWrapper;50import freemarker.template.Template;51import freemarker.template.TemplateException;52import freemarker.template.TemplateModel;5354public class UMA {5556public static final String UMA_TARGETS_IN_TREE = "UMA_TARGETS_IN_TREE";57public static final String UMA_TARGETS_IN_TREE_VAR = "$("+UMA_TARGETS_IN_TREE+")";58public static final String UMA_PATH_TO_ROOT = "UMA_PATH_TO_ROOT";59public static final String UMA_PATH_TO_ROOT_VAR = "$("+UMA_PATH_TO_ROOT+")";60public static final String OMR_DIR = "OMR_DIR";61public static final String OMR_DIR_VAR = "$("+OMR_DIR+")";62public static final String UMA_TARGET_MAKEFILE = "targets.mk";63public static final String UMA_MAKELIB_DIR = "makelib";64public static final String UMA_MACROS_FILE = "uma_macros.mk";65public static final String UMA_MACROS_PATH_FROM_ROOT = UMA_MAKELIB_DIR + "/" + UMA_MACROS_FILE;66public static final String UMA_TARGET_MAKEFILE_WITH_PATH = UMA_MAKELIB_DIR + "/" + UMA_TARGET_MAKEFILE;67public static final String UMA_MKCONSTANTS_FILE = "mkconstants.mk";68public static final String UMA_MKCONSTANTS_PATH_FROM_ROOT = UMA_MAKELIB_DIR + "/" + UMA_MKCONSTANTS_FILE;69public static final String UMA_ARTIFACT_CFLAGS_LABEL = "A_CFLAGS";70public static final String UMA_ARTIFACT_CXXFLAGS_LABEL = "A_CXXFLAGS";71public static final String UMA_ARTIFACT_CPPFLAGS_LABEL = "A_CPPFLAGS";72public static final String UMA_ARTIFACT_ASFLAGS_LABEL = "A_ASFLAGS";7374public static final String FREEMARKER_UMA = "uma";757677public static final int NUM_OBJECTS_PER_LINE=10;7879static UMA uma;8081public static UMA getUma() {82return uma;83}8485public IPlatform getPlatform() {86return platform;87}8889IPlatform platform;90IConfiguration configuration;91Configuration freemarkerConfig;92ISinglePredicateEvaluator singlePredicateEvaluator;93Vector<Module> modules;94Hashtable<String, Artifact> artifactMap = new Hashtable<String,Artifact>();95Hashtable<String, Artifact> artifactLocationMap = new Hashtable<String, Artifact>();96String rootDirectory;97TemplateLoader templateLoader;98String phasePrefix;99100static final String UMA_MAKEFILE_PHASE_PREFIX = "makefile_phase_prefix";101102public UMA(IConfiguration configuration, ISinglePredicateEvaluator singlePredicateEvaluator, String rootDir) throws UMAException {103this.configuration = configuration;104this.platform = configuration.getPlatform();105this.singlePredicateEvaluator = singlePredicateEvaluator;106this.rootDirectory = rootDir;107if ( !rootDir.endsWith(File.separator) ) this.rootDirectory += File.separator;108109// ensure that the root directory exists before proceeding.110File file = new File(this.rootDirectory);111if ( !file.exists() ) {112throw new UMAException("Error: Source directory " + file.getAbsolutePath() + " does not exist.");113}114115UMA.uma = this;116117phasePrefix = configuration.replaceMacro(UMA_MAKEFILE_PHASE_PREFIX);118if ( phasePrefix == null ) {119phasePrefix = "";120} else {121phasePrefix += " ";122}123124125// Initialize the Freemarker configuration126freemarkerConfig = new Configuration();127// Specify how templates will see the data model.128freemarkerConfig.setObjectWrapper(new DefaultObjectWrapper());129this.templateLoader = new TemplateLoader();130freemarkerConfig.setTemplateLoader(this.templateLoader);131}132133public IConfiguration getConfiguration() {134return configuration;135}136137public ISinglePredicateEvaluator getSinglePredicateEvaluator() {138return singlePredicateEvaluator;139}140141public Vector<Module> getModules() {142return modules;143}144145public void addArtifact( Artifact artifact ) throws UMAException {146String artifactKey = artifact.getArtifactKey();147Artifact artifactInMap = artifactMap.get(artifactKey);148if ( artifactInMap != null ) {149throw new DuplicateArtifactKeyException("Duplicate artifact key found [" + artifactKey + "] in file " + artifact.getContainingFile() + " already found in file " + artifactInMap.getContainingFile() );150}151artifactMap.put(artifactKey, artifact);152}153154public void validateArtifactLocations() throws DuplicateArtifactKeyException, UMAException {155156// Artifacts won't know if they are in bundles until all artifacts are created157for (Artifact artifact : getArtifacts().values()) {158if ( artifact.evaluate() ) {159String artifactLocationKey = platform.getLibOnDiskName(artifact);160Artifact artifactLocationInMap = artifactLocationMap.get(artifactLocationKey);161if ( artifactLocationInMap != null ) {162throw new DuplicateArtifactKeyException("Duplicate artifact locations found [" + artifactLocationKey + "] in file " + artifact.getContainingFile() + " already found in file " + artifactLocationInMap.getContainingFile() );163}164artifactLocationMap.put(artifactLocationKey, artifact);165}166}167}168169public Artifact getArtifact(String artifactName) {170return artifactMap.get(artifactName);171}172173public Artifact getBundleArtifact(String artifactName) throws UMAException {174for (Artifact artifact : artifactMap.values()) {175if (artifact.isBundle()) {176if (artifact.getTargetName().equals(artifactName)) {177return artifact;178}179}180}181return null;182}183184public Hashtable<String, Artifact> getArtifacts() {185return artifactMap;186}187188189190public String getRootDirectory() {191return rootDirectory;192}193194public void generate() throws UMAException {195196Parser parser = new Parser(this);197if ( !parser.parse() ) {198return;199}200201modules = parser.getModules();202203platform.decorateModules(modules);204205// Freemarker invocation206207try {208Map<String, TemplateModel> map = new HashMap<String, TemplateModel>();209map.put(FREEMARKER_UMA, new com.ibm.uma.freemarker.UMA());210for ( String tmp : templateLoader.getTemplates() ) {211Template template = freemarkerConfig.getTemplate(tmp);212String filename = tmp.substring(0, tmp.lastIndexOf(".ftl"));213StringWriter writer = new StringWriter();214template.process(map, writer);215new FileAssistant(this.rootDirectory+filename, writer.getBuffer()).writeToDisk();216}217} catch (IOException e) {218throw new UMAException(e);219220} catch (TemplateException e) {221throw new UMAException(e);222}223224writeTargetInformationMacrosFile();225226// top level module is the first in the list.227Module rootModule = null;228for ( Module module : modules ) {229if ( module.isTopLevel() ) {230if ( rootModule != null ) {231throw new UMAException("Error: more than one root module " + rootModule.getFullName() + " and " + module.getFullName());232}233rootModule = module;234}235}236if ( rootModule == null ) {237throw new UMAException("Error: no " + configuration.getMetadataFilename() + " found in the root directory " + getRootDirectory());238}239writeDirectoryMakefile(rootModule);240241Logger.getLogger().println(Logger.InformationL1Log, "Complete");242}243244class LineWrapMakefileDirective {245int itemCount = 0;246int maxItems = NUM_OBJECTS_PER_LINE;247String underMaxSeperator = " ";248String overMaxSeperator = "\\\n ";249StringBuffer stringBuffer;250251LineWrapMakefileDirective(StringBuffer stringBuffer) {252this.stringBuffer = stringBuffer;253}254255LineWrapMakefileDirective(StringBuffer stringBuffer, String underMaxSeperator, String overMaxSeperator) {256this.stringBuffer = stringBuffer;257this.underMaxSeperator = underMaxSeperator;258this.overMaxSeperator = overMaxSeperator;259}260261void addItem(String item) {262if (itemCount<maxItems) {263itemCount++;264stringBuffer.append(underMaxSeperator);265} else {266itemCount = 1;267stringBuffer.append(overMaxSeperator);268}269stringBuffer.append(item);270}271}272273// This function takes a module and creates a makefile for the directory,274// then recursively calls this function on all sub-modules.275void writeDirectoryMakefile(Module module) throws UMAException {276if ( !module.evaluate() ) return;277278String modulePath = new File(module.getModulePath()).getParent();279Logger.getLogger().println(Logger.InformationL2Log, "Producing makefile(s) for " + modulePath );280281for ( Artifact artifact : module.getArtifacts() ) {282writeMakefileForArtifact(artifact);283}284285if ( module.requiresDispatchMakefile() ) {286// There needs to be a dispatch makefile287String makefileName = modulePath + File.separator +"makefile";288StringBuffer buffer = new StringBuffer();289FileAssistant fa = new FileAssistant(makefileName, buffer);290buffer.append(configuration.getMakefileCopyrightNotice());291String pathToRoot = determinePathToRoot(module);292293294Vector<String> targets = new Vector<String>();295Vector<String> specialTargets = new Vector<String>();296for ( Artifact artifact : module.getAllArtifactsInTree() ) {297if ( !artifact.evaluate() ) continue;298if ( artifact.getType() == Artifact.TYPE_TARGET ) {299if ( artifact.includeInAllTarget() ) {300/*301* The separation of targets into targets and specialTargets302* is being done to allow the 'TARGET' type artifacts to be built first.303* This is a weak way of saying that the whole system is dependent on304* these targets without having to add the dependency to each and every305* artifact.306*307* This only works when not using -j on gmake and because308* gmake will do the targets in the order they are on the dependency line.309*310*/311specialTargets.add(artifact.getMakefileName());312}313} else {314if (artifact.includeInAllTarget()) {315targets.add(artifact.getMakefileName());316}317}318}319320buffer.append(UMA_PATH_TO_ROOT+"=" + pathToRoot + "\n");321buffer.append(OMR_DIR+"?=" + pathToRoot + "omr\n");322StringBuffer targetsInTreeBuffer = new StringBuffer();323LineWrapMakefileDirective lwmd = new LineWrapMakefileDirective(targetsInTreeBuffer);324targetsInTreeBuffer.append(UMA_TARGETS_IN_TREE+"=");325for ( String target : specialTargets ) {326lwmd.addItem(target);327}328for ( String target : targets ) {329lwmd.addItem(target);330}331buffer.append(targetsInTreeBuffer.toString());332333buffer.append("\n\ninclude " + UMA_PATH_TO_ROOT_VAR + UMA_MKCONSTANTS_PATH_FROM_ROOT + "\n");334buffer.append("include " + UMA_PATH_TO_ROOT_VAR + UMA_MACROS_PATH_FROM_ROOT + "\n\n");335336buffer.append(phasePrefix + "all: " + UMA_TARGETS_IN_TREE_VAR + "\n\n");337338buffer.append("clean: $(addprefix clean_," + UMA_TARGETS_IN_TREE_VAR + ")\n\n");339340buffer.append("ddrgen: $(addprefix ddrgen_," + UMA_TARGETS_IN_TREE_VAR + ")\n\n");341342buffer.append(343"static: UMA_STATIC_BUILD=1\n" +344" export UMA_STATIC_BUILD\n\n" +345"static:\n" +346" $(MAKE) -f makefile\n\n\n");347348349for ( int phase=0; phase<configuration.numberOfPhases(); phase++ ) {350Vector<String> phaseTargets = new Vector<String>();351Vector<String> specialPhaseTargets = new Vector<String>();352for ( Artifact artifact : module.getAllArtifactsInTree() ) {353if ( !artifact.evaluate() ) continue;354if ( !artifact.isInPhase(phase) ) continue;355if ( artifact.getType() == Artifact.TYPE_TARGET ) {356/*357* The separation of targets into phaseTargets and specialPhaseTargets358* is being done to allow the 'TARGET' type artifacts to be built first.359* This is a weak way of saying that the whole system is dependent on360* these targets without having to add the dependency to each and every361* artifact.362*363* This only works when not using -j on gmake and because364* gmake will do the targets in the order they are on the dependency line.365*366*/367specialPhaseTargets.add(artifact.getMakefileName());368} else {369phaseTargets.add(artifact.getMakefileName());370}371}372373buffer.append(phasePrefix + "phase_" + configuration.phaseName(phase) + ":");374StringBuffer targetsInPhaseBuffer = new StringBuffer();375lwmd = new LineWrapMakefileDirective(targetsInPhaseBuffer);376for ( String target : specialPhaseTargets ) {377lwmd.addItem(target);378}379for ( String target : phaseTargets ) {380lwmd.addItem(target);381}382buffer.append( targetsInPhaseBuffer.toString() + "\n" );383}384385buffer.append( "\n" );386387for ( Artifact artifact : module.getAllArtifactsInTree() ) {388if ( !artifact.evaluate() ) continue;389switch (artifact.getType()) {390case Artifact.TYPE_SUBDIR:391// Ignore this type of artifact. It is only used392// to glue the tree together.393break;394case Artifact.TYPE_TARGET:395buffer.append( "clean_" + artifact.getMakefileName() + ":\n" );396for ( Command command : artifact.getCommands() ) {397if ( !command.evaluate() || command.getType() != Command.TYPE_CLEAN ) continue;398buffer.append("\t" + command.getCommand() + "\n");399}400buffer.append( "\n" );401402buffer.append( "ddrgen_" + artifact.getMakefileName() + ":\n" );403for ( Command command : artifact.getCommands() ) {404if ( !command.evaluate() || command.getType() != Command.TYPE_DDRGEN ) continue;405buffer.append("\t" + command.getCommand() + "\n");406}407buffer.append( "\n" );408409buffer.append( artifact.getMakefileName() + ":" );410for ( Dependency dependency : artifact.getDependendies() ) {411if ( !dependency.evaluate() ) continue;412buffer.append( " " + dependency.getDependency() );413}414buffer.append( "\n" );415for ( Command command : artifact.getCommands() ) {416if ( !command.evaluate() || command.getType() != Command.TYPE_ALL ) continue;417buffer.append("\t" + command.getCommand() + "\n");418}419buffer.append( "\n" );420break;421default:422buffer.append( "clean_" + artifact.getMakefileName() + ":\n\t$(" + artifact.getMakefileName() + "_build) clean\n\n");423buffer.append( "ddrgen_" + artifact.getMakefileName() + ":\n\t$(" + artifact.getMakefileName() + "_build) ddrgen\n\n");424buffer.append( artifact.getMakefileName() + ": $(" + artifact.getMakefileName() + "_dependencies)\n\t$(" + artifact.getMakefileName() + "_build)\n\n");425break;426}427}428429if ( module.isTopLevel() ) {430platform.writeTopLevelTargets(buffer);431}432433buffer.append(".PHONY: all clean ddrgen");434StringBuffer phonyTargetsBuffer = new StringBuffer();435lwmd = new LineWrapMakefileDirective(phonyTargetsBuffer);436for ( String phonyTarget : specialTargets ) {437lwmd.addItem(phonyTarget);438lwmd.addItem(" clean_" + phonyTarget);439}440for ( String phonyTarget : targets ) {441lwmd.addItem(phonyTarget);442lwmd.addItem(" clean_" + phonyTarget);443}444buffer.append(phonyTargetsBuffer.toString()+"\n");445fa.writeToDisk();446447}448449for ( Artifact artifact : module.getArtifacts() ) {450if ( artifact.getType() == Artifact.TYPE_SUBDIR ) {451SubdirArtifact subdirArtifact = (SubdirArtifact) artifact;452writeDirectoryMakefile(subdirArtifact.getSubdirModule());453}454}455}456457void addDependencies( Vector<Library> libraries, Hashtable<String, LinkedHashSet<String>> buildDependencies, Artifact artifact ) throws UMAException {458String target = artifact.getMakefileName();459LinkedHashSet<String> deps = buildDependencies.get(target);460if ( deps == null ) {461deps = new LinkedHashSet<String>();462buildDependencies.put(target, deps);463}464for ( Library library : libraries ) {465if ( library.evaluate() ) {466if ( library.getType() != Library.TYPE_BUILD ) continue;467Artifact libArtifact = getArtifact(library.getName());468if ( libArtifact == null ) continue;469String libName = libArtifact.getMakefileName();470if ( libArtifact.isInBundle() ) {471Artifact bundle = getBundleArtifact(libArtifact.getBundle());472if (artifact != bundle) {473/* If we are not dealing with the bundle itself, then substitute the474* bundle name for the library. */475libName = bundle.getMakefileName();476}477}478if ( !deps.contains(libName) && !libName.equalsIgnoreCase(target)) {479deps.add(libName);480}481}482}483for ( Dependency artifactDependency : artifact.getDependendies() ) {484if ( artifactDependency.evaluate() ) {485String dependency = artifactDependency.getDependency();486if ( !deps.contains(dependency) && !dependency.equalsIgnoreCase(target)) {487deps.add(dependency);488}489}490}491}492493void expandLibraryDependencies(Artifact artifact, StringBuffer libLocations) throws UMAException {494switch (artifact.getType()) {495case Artifact.TYPE_BUNDLE: // FALL-THRU496case Artifact.TYPE_STATIC: // FALL-THRU497case Artifact.TYPE_SHARED:498libLocations.append(artifact.getTargetNameWithScope() + "_deps=" + artifact.getTargetName());499Hashtable<String, Library> libs = artifact.getAllLibrariesThisArtifactDependsOn();500for ( Library lib : libs.values() ) {501if ( lib.evaluate() ) {502switch ( lib.getType() ) {503case Library.TYPE_MACRO:504String mlibs = platform.replaceMacro(lib.getName());505if (mlibs != null) {506libLocations.append(" " + mlibs);507}508continue;509}510libLocations.append(" " + lib.getName());511}512}513514/* for bundles emit a dependency on element in the bundle */515if (artifact.getType() == Artifact.TYPE_BUNDLE) {516String bundleName = artifact.getTargetName();517for (Artifact artifactCursor : artifactMap.values()) {518if (!artifactCursor.evaluate()) {519continue;520}521if (!artifactCursor.isInBundle()) {522continue;523}524if (!artifactCursor.getBundle().equalsIgnoreCase(bundleName)) {525continue;526}527libLocations.append(" " + artifactCursor.getArtifactKey());528}529}530libLocations.append("\n\n");531break;532}533}534535536537void writeTargetInformationMacrosFile() throws UMAException {538/*539* Buffer for information about which libraries are static vs. shared540* and their locations on disk and references on the target and link lines.541*/542StringBuffer libLocations = new StringBuffer();543/*544* Buffer for target rules.545*/546StringBuffer targetRules = new StringBuffer();547548/*549* A couple of hashtable to gather information an artifacts build dependencies.550*/551Hashtable<String, LinkedHashSet<String>> buildDependencies = new Hashtable<String,LinkedHashSet<String>>();552Hashtable<String, LinkedHashSet<String>> staticBuildDependencies = new Hashtable<String,LinkedHashSet<String>>();553554for ( Module module : modules) {555if ( !module.evaluate() ) continue;556// determine build dependencies557for (Artifact artifact : module.getArtifacts()) {558if ( !artifact.evaluate() ) continue;559switch (artifact.getType()) {560case Artifact.TYPE_BUNDLE: // Fall Through561case Artifact.TYPE_SHARED:562libLocations.append(artifact.getTargetNameWithScope()+"_alllib="+artifact.getTargetName()+"\n");563libLocations.append(artifact.getTargetNameWithScope()+"_sharedlib="+artifact.getTargetName()+"\n");564platform.addLibraryLocationInformation(artifact, libLocations);565expandLibraryDependencies(artifact, libLocations);566break;567case Artifact.TYPE_STATIC:568libLocations.append(artifact.getTargetNameWithScope()+"_alllib="+artifact.getTargetName()+"\n");569libLocations.append(artifact.getTargetNameWithScope()+"_staticlib="+artifact.getTargetName()+"\n");570platform.addLibraryLocationInformation(artifact, libLocations);571expandLibraryDependencies(artifact, libLocations);572break;573case Artifact.TYPE_EXECUTABLE:574break;575}576577switch (artifact.getType()) {578case Artifact.TYPE_BUNDLE: // Fall Through579case Artifact.TYPE_SHARED: // Fall Through580case Artifact.TYPE_STATIC: // Fall Through581case Artifact.TYPE_EXECUTABLE: // Fall Through582targetRules.append(583artifact.getMakefileName() + "_build" + "=+$(MAKE) $(UMA_WINDOWS_PARRALLEL_HACK) -C " + UMA_PATH_TO_ROOT_VAR + artifact.getContainingModule().getFullName() + " -f " + artifact.getMakefileFileName() + "\n");584break;585}586587addDependencies( artifact.getLibraries(), buildDependencies, artifact);588addDependencies( artifact.getStaticLinkLibraries(), staticBuildDependencies, artifact);589}590}591592/*593* Write uma macros helper makefile. This file contains several variable definitions that allow594* easy reference to information about the artifacts. e.g.,595*/596File makelibDirectory = new File(UMA.getUma().getRootDirectory() + UMA_MAKELIB_DIR);597makelibDirectory.mkdir();598FileAssistant fa = new FileAssistant(UMA.getUma().getRootDirectory() + UMA_MACROS_PATH_FROM_ROOT );599StringBuffer buffer = fa.getStringBuffer();600buffer.append("# UMA Macro Helper Definition Makefile\n" );601buffer.append(configuration.getMakefileCopyrightNotice());602buffer.append(libLocations.toString()+"\n\n\n");603604for (String target : buildDependencies.keySet()) {605buffer.append( "\n");606for ( String dependency : buildDependencies.get(target) ) {607buffer.append(target + "_dependencies+=$(findstring " + dependency + ","+ UMA_TARGETS_IN_TREE_VAR +")\n");608}609buffer.append("\n");610}611buffer.append("\n\nifdef UMA_STATIC_BUILD\n\n");612for (String target : staticBuildDependencies.keySet()) {613buffer.append( "\n");614for ( String dependency : staticBuildDependencies.get(target) ) {615buffer.append(target + "_dependencies+=$(findstring " + dependency + ","+ UMA_TARGETS_IN_TREE_VAR +")\n");616}617buffer.append("\n");618}619buffer.append("\n\nendif\n\n");620621buffer.append( targetRules.toString() );622623fa.writeToDisk();624}625626void writeMakefileForArtifact(Artifact artifact) throws UMAException {627if ( !artifact.evaluate() ||628artifact.getType() == Artifact.TYPE_SUBDIR ||629artifact.getType() == Artifact.TYPE_REFERENCE ||630artifact.getType() == Artifact.TYPE_TARGET) return;631632Module module = artifact.getContainingModule();633String modulePath = new File(module.getModulePath()).getParent();634String makefileName = artifact.getMakefileFileName();635makefileName = modulePath + File.separator + makefileName;636637platform.writePlatformSpecificFiles(artifact);638639FileAssistant fa = new FileAssistant(makefileName);640StringBuffer buffer = fa.getStringBuffer();641buffer.append("# Makefile for '" + artifact.getMakefileName() + "'\n" );642buffer.append(configuration.getMakefileCopyrightNotice());643String pathToRoot = determinePathToRoot(module);644buffer.append(UMA_PATH_TO_ROOT+"=" + pathToRoot + "\n");645buffer.append(OMR_DIR+"?=" + pathToRoot + "omr\n");646switch ( artifact.getType() ) {647case Artifact.TYPE_BUNDLE: // fall-thru648case Artifact.TYPE_SHARED:649buffer.append("UMA_TARGET_TYPE=DLL\n");650break;651case Artifact.TYPE_EXECUTABLE:652buffer.append("UMA_TARGET_TYPE=EXE\n");653break;654case Artifact.TYPE_STATIC:655buffer.append("UMA_TARGET_TYPE=LIB\n");656break;657}658buffer.append("UMA_TARGET_NAME=" + artifact.getTargetNameWithScope() + "\n");659660/* On OSX, <LIB_NAME_DYLIB>.dylib should match the -install_name <LIB_NAME_INSTALL>.661* Otherwise, the linker is unable to find the required library. Currently, LIB_NAME_DYLIB662* doesn't match LIB_NAME_INSTALL. LIB_NAME_DYLIB has major and minor build versions663* appended whereas LIB_NAME_INSTALL doesn't contain version info. UMA_LIB_NAME will contain664* LIB_NAME_INSTALL with major and minor build versions.665*/666buffer.append("UMA_LIB_NAME=" + platform.getTargetNameWithRelease(artifact) + "\n");667668if ( artifact.getTargetPath() != null ) {669buffer.append("UMA_TARGET_PATH=" + UMA_PATH_TO_ROOT_VAR + artifact.getTargetPath()+"\n");670}671if ( artifact.flagSet("isCPlusPlus") ) {672buffer.append("UMA_IS_C_PLUS_PLUS=1\n");673}674platform.addArtifactSpecificMakefileInformation(artifact, buffer);675676buffer.append("\ninclude "+UMA_PATH_TO_ROOT_VAR + UMA_MKCONSTANTS_PATH_FROM_ROOT + "\n\n");677writeMakefileIncludeLine(buffer, module, artifact);678writeMakefileLibraryLine(buffer, module, artifact);679buffer.append(platform.writeMakefileFlagsLine(artifact).toString());680writeMakefileObjectLine(buffer, module, artifact);681buffer.append(platform.writeMakefileExtras(artifact).toString());682writeMakefileStubs(buffer, module, artifact);683writeMakefileVPathInformation(buffer, module, artifact);684buffer.append(platform.writeMakefilePostscript(artifact).toString());685if (artifact.getCommands().isEmpty()) {686buffer.append("\ninclude "+UMA_PATH_TO_ROOT_VAR+UMA_TARGET_MAKEFILE_WITH_PATH+"\n");687} else {688/* Support custom recipes for building a target.689*690* If module.xml specifies <commands /> for this artifact, we will use the commands691* to build the on-disk artifact, instead of the rules in targets.mk.692*/693694/* uma_macros.mk defines the names of the ondisk artifact and its dependencies */695buffer.append("include " + UMA_PATH_TO_ROOT_VAR + UMA_MACROS_PATH_FROM_ROOT + "\n\n");696697/* Defines the default target.698*699* $($(target)_ondisk): $($(target)_dependencies)700* commands with type="all"701*/702buffer.append("$(" + artifact.getTargetNameWithScope() + "_ondisk): ");703buffer.append("$(" + artifact.getTargetNameWithScope() + "_dependencies)\n");704for (Command command : artifact.getCommands()) {705if (!command.evaluate() || command.getType() != Command.TYPE_ALL)706continue;707buffer.append("\t" + command.getCommand() + "\n");708}709buffer.append("\n");710711/* Defines the clean target.712*713* clean:714* commands with type="clean"715*/716buffer.append("clean:\n");717for (Command command : artifact.getCommands()) {718if (!command.evaluate() || command.getType() != Command.TYPE_CLEAN)719continue;720buffer.append("\t" + command.getCommand() + "\n");721}722buffer.append("\n");723724/* Defines the ddrgen target.725*726* ddrgen:727* commands with type="ddrgen"728*/729buffer.append("ddrgen:\n");730for (Command command : artifact.getCommands()) {731if (!command.evaluate() || command.getType() != Command.TYPE_DDRGEN)732continue;733buffer.append("\t" + command.getCommand() + "\n");734}735buffer.append("\n");736}737fa.writeToDisk();738}739740void writeMakefileVPathInformation( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {741for ( VPath vpath : artifact.getVPaths() ) {742if ( !vpath.evaluate() ) continue;743if ( vpath.getPath() == null ) continue;744// vpath for a any pattern745buffer.append("vpath " + vpath.getPattern() + " ");746if ( vpath.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );747buffer.append(vpath.getPath() + "\n");748if ( vpath.isAugmentObjects() ) {749buffer.append("UMA_OBJECTS+=" + vpath.getObjectFile() + "\n");750}751if ( vpath.isAugmentIncludes() ) {752buffer.append("UMA_INCLUDES+=");753if ( vpath.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );754buffer.append(vpath.getPath() + "\n");755}756757}758}759760void writeMakefileIncludeLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {761Vector<Include> includes = artifact.getIncludes();762763buffer.append("UMA_INCLUDES=. " + configuration.getAdditionalIncludesForArtifact(artifact));764765for ( Include include : includes ) {766if (include.evaluate()) {767if ( include.getType() == VPath.TYPE_ROOT_PATH ) buffer.append( UMA_PATH_TO_ROOT_VAR );768buffer.append(include.getPath() + " ");769}770}771buffer.append("\n");772}773774/**775* @param artifact artifact being built776* @param type The type of library to find.777* @param forStatic Whether these libraries are for an UMA_STATIC_BUILD778* @param libArtifact artifact being linked in779* @throws UMAException780*/781private String getLibraryDependenciesOfType( Artifact artifact, int type, boolean forStatic, Artifact libArtifact ) throws UMAException {782783String libName = libArtifact.getTargetNameWithScope();784785if ( type == Library.TYPE_BUILD ) {786/* static versions use the library name without any tweaks */787if (forStatic) {788return libName + " ";789}790791/* unbundled artifacts don't require special treatment */792if (!libArtifact.isInBundle()) {793return libName + " ";794}795}796797StringBuilder stringBuilder = new StringBuilder();798799/* executables/external DLL's should link in the *actual* code, not the bundle */800if (!artifact.isInBundle() && (artifact.getType() == Artifact.TYPE_EXECUTABLE) ) {801802if ( type == Library.TYPE_BUILD ) {803stringBuilder.append(libName + " ");804}805806for (Library inheritedLib : libArtifact.getLibraries()) {807if (!inheritedLib.evaluate()) {808continue;809}810811Artifact inheritedLibArtifact = getArtifact(inheritedLib.getName());812if ( inheritedLib.getType() == Library.TYPE_BUILD) {813/* Do not include the library if its artifact is not included */814if (null == inheritedLibArtifact || !inheritedLibArtifact.evaluate()) {815continue;816}817}818819if (inheritedLib.getType() == type) {820/* macro libraries will have their name mangled */821if (type == Library.TYPE_MACRO) {822if (null != inheritedLibArtifact && !inheritedLibArtifact.evaluate()) {823continue;824}825String libs = platform.replaceMacro(inheritedLib.getName());826if ( libs != null ) {827stringBuilder.append(libs + " ");828}829} else {830stringBuilder.append(inheritedLib.getName() + " ");831}832}833834835}836return stringBuilder.toString();837}838839if ( type == Library.TYPE_BUILD ) {840/* if we are building the bundle then used unmodified names */841Artifact bundle = getBundleArtifact(libArtifact.getBundle());842if (bundle == artifact) {843return stringBuilder.toString();844}845846/* otherwise the library is in a bundle and we should substitute the bundle name (ugh) */847stringBuilder.append(bundle.getArtifactKey() + " ");848return stringBuilder.toString();849}850851return "";852}853854/**855* @param artifact artifact being built856* @param libraries The list of libraries which we are through.857* @param type The type of library to find.858* @param forStatic Whether these libraries are for an UMA_STATIC_BUILD859* @throws UMAException860*/861String getLibrariesOfType( Artifact artifact, Vector<Library> libraries, int type, boolean forStatic ) throws UMAException {862if ( libraries.size() < 1 )863return "";864865StringBuilder stringBuilder = new StringBuilder();866867for ( Library library : libraries ) {868if ( library.evaluate()) {869if ( library.getType() == Library.TYPE_BUILD ) {870/* If the library is an artifact, we want to include its dependencies as871* well as itself.872*/873Artifact libArtifact = getArtifact(library.getName());874if ( libArtifact != null ) {875if ( libArtifact.evaluate() ) {876stringBuilder.append(getLibraryDependenciesOfType(artifact, type, forStatic, libArtifact));877}878} else {879Logger.getLogger().println(Logger.WarningLog, "Warning: unknown library reference " + library.getName() + " in: " + artifact.getContainingFile());880}881} else if (library.getType() == type) {882/* macro libraries will have their name mangled */883if (type == Library.TYPE_MACRO) {884String libs = platform.replaceMacro(library.getName());885if ( libs != null ) {886stringBuilder.append(libs + " ");887}888} else {889stringBuilder.append(library.getName() + " ");890}891}892}893}894return stringBuilder.toString();895}896897void writeMakefileLibraryLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {898if ( artifact.getType() != Artifact.TYPE_BUNDLE && artifact.getType() != Artifact.TYPE_SHARED && artifact.getType() != Artifact.TYPE_EXECUTABLE) return;899Vector<Library> libraries = artifact.getLibraries();900901String libs = getLibrariesOfType(artifact, libraries, Library.TYPE_BUILD, false);902libs = libs + getLibrariesOfType(artifact, libraries, Library.TYPE_SYSTEM, false);903libs = libs + getLibrariesOfType(artifact, libraries, Library.TYPE_MACRO, false);904if (libs.length() != 0) {905buffer.append("UMA_LIBRARIES := " + libs + "\n");906}907908libs = getLibrariesOfType(artifact, libraries, Library.TYPE_EXTERNAL, false);909if (libs.length() != 0) {910buffer.append("UMA_EXTERNAL_LIBRARIES := " + libs + "\n");911}912913/* Static libraries will have their dependencies compiled in */914libraries = artifact.getStaticLinkLibraries();915libs = getLibrariesOfType(artifact, libraries, Library.TYPE_BUILD, true);916if (libs.length() != 0) {917buffer.append("UMA_STATIC_LIBRARIES := " + libs + "\n");918}919}920921void writeMakefileObjectLine( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {922// Add all objects into a set, eliminating duplicates.923HashSet<String> objtable = new HashSet<String>();924Vector<Object> objects = artifact.getObjects();925for ( Object object : objects ) {926if ( object.evaluate() ) {927switch (object.getType()) {928case Object.SINGLE:929if ( !objtable.contains(object.getName()) ) {930objtable.add(object.getName());931}932break;933case Object.GROUP:934Vector<String> newGroups = new Vector<String>();935newGroups.add(object.getName());936while ( newGroups != null ) {937Vector<String> groups = newGroups;938newGroups = null;939for ( String groupName : groups ) {940Objects objs = module.getObjects().get(groupName);941if ( objs == null ) {942throw new UMAException("Error: bad object group name [" +groupName+"] in " + module.getModulePath() +"." );943}944if ( objs.evaluate() ) {945for ( Object obj : objs.getObjects()) {946if ( obj.evaluate() ) {947switch (obj.getType()) {948case Object.SINGLE:949if ( !objtable.contains(obj.getName()) ) {950objtable.add(obj.getName());951}952break;953case Object.GROUP:954if ( newGroups == null ) {955newGroups = new Vector<String>();956}957newGroups.add(obj.getName());958break;959}960}961}962}963}964}965break;966} // switch967}968}969970StringBuffer objectBuffer = new StringBuffer();971if ( objtable.size() >= 1 ) {972produceObjectLine(objectBuffer, objtable, "UMA_OBJECTS");973}974HashSet<String> targetSpecificObjects = new HashSet<String>();975produceObjectLine(objectBuffer, targetSpecificObjects, "UMA_OBJECTS+");976977objtable = new HashSet<String>();978platform.addTargetSpecificObjectsForStaticLink(objtable, artifact);979if ( objtable.size() >= 1) {980produceObjectLine(objectBuffer, objtable, "UMA_STATIC_OBJECTS");981}982if ( objectBuffer.length() > 0 ) {983buffer.append(objectBuffer.toString());984}985}986987void produceObjectLine( StringBuffer objectBuffer, HashSet<String> objtable, String tag) {988objectBuffer.append(tag + "=");989int objectsWritten = 0;990for ( String obj : objtable ) {991objectBuffer.append(" " + obj);992objectsWritten ++;993if ( objectsWritten % UMA.NUM_OBJECTS_PER_LINE == 0 ) {994objectBuffer.append("\\\n");995}996}997objectBuffer.append("\n");998}9991000void writeMakefileStubs( StringBuffer buffer, Module module, Artifact artifact ) throws UMAException {1001Vector<MakefileStub> makefileStubs = artifact.getMakefileStubs();1002if ( !artifact.appendRelease() ) {1003buffer.append("UMA_DO_NOT_APPEND_RELEASE_TO_DLL=1\n");1004}1005for ( MakefileStub stub : makefileStubs ) {1006if ( stub.evaluate() ) {1007String[] stubs = stub.toString().split("\\\\n");1008for (int k=0; k<stubs.length; k++) {1009buffer.append(stubs[k] + "\n");1010}1011}1012}1013}10141015String determinePathToRoot( Module module ) {1016String pathToRoot = "";1017int depth = module.getModuleDepth();1018for ( int i=0; i<depth; i++ ) {1019pathToRoot = pathToRoot + "../";1020}1021if (pathToRoot.equals("")) return "./";1022return pathToRoot;1023}1024}102510261027