Mercurial > hg > graal-compiler
comparison mx.graal/mx_graal_makefile.py @ 22017:66dd063eb6a0
renamed mx/ to mx.graal/ in preparation for working with mxtool2
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 17 Jun 2015 13:56:55 +0200 |
parents | mx/mx_graal_makefile.py@72129dd49bc0 |
children | 0e095e2c24e2 |
comparison
equal
deleted
inserted
replaced
22016:f2cf8824040b | 22017:66dd063eb6a0 |
---|---|
1 # | |
2 # ---------------------------------------------------------------------------------------------------- | |
3 # | |
4 # Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. | |
5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
6 # | |
7 # This code is free software; you can redistribute it and/or modify it | |
8 # under the terms of the GNU General Public License version 2 only, as | |
9 # published by the Free Software Foundation. | |
10 # | |
11 # This code is distributed in the hope that it will be useful, but WITHOUT | |
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 # version 2 for more details (a copy is included in the LICENSE file that | |
15 # accompanied this code). | |
16 # | |
17 # You should have received a copy of the GNU General Public License version | |
18 # 2 along with this work; if not, write to the Free Software Foundation, | |
19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 # | |
21 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
22 # or visit www.oracle.com if you need additional information or have any | |
23 # questions. | |
24 # | |
25 # ---------------------------------------------------------------------------------------------------- | |
26 # | |
27 import mx, mx_graal, os | |
28 from argparse import ArgumentParser, REMAINDER | |
29 | |
30 | |
31 class Makefile: | |
32 def __init__(self): | |
33 self.rules = [] | |
34 self.definitions = [] | |
35 | |
36 def add_rule(self, s): | |
37 self.rules.append(s) | |
38 | |
39 def add_definition(self, s): | |
40 self.definitions.append(s) | |
41 | |
42 def generate(self): | |
43 return "\n\n".join(self.definitions + self.rules) | |
44 | |
45 | |
46 def build_makefile(args): | |
47 """Creates a Makefile which is able to build distributions without mx | |
48 | |
49 The return value indicates how many files were modified""" | |
50 parser = ArgumentParser(prog='mx makefile') | |
51 parser.add_argument('-o', action='store', dest='output', help='Write contents to this file.') | |
52 parser.add_argument('selectedDists', help="Selected distribution names which are going to be built with make.", nargs=REMAINDER) | |
53 opts = parser.parse_args(args) | |
54 | |
55 if opts.selectedDists == None or len(opts.selectedDists) == 0: | |
56 opts.selectedDists = [d.name for d in mx_graal._jdkDeployedDists if d.partOfHotSpot] | |
57 mf = Makefile() | |
58 commandline = " ".join(["mx.sh", "makefile"] + args) | |
59 if do_build_makefile(mf, opts.selectedDists, commandline): | |
60 contents = mf.generate() | |
61 if opts.output == None: | |
62 print contents | |
63 else: | |
64 if mx.update_file(opts.output, contents, showDiff=True): | |
65 return 1 | |
66 return 0 | |
67 | |
68 def short_dist_name(name): | |
69 return name.replace("COM_ORACLE_", "") | |
70 | |
71 def filter_projects(deps, t): | |
72 def typeFilter(project): # filters | |
73 if isinstance(project, str): | |
74 project = mx.dependency(project, True) | |
75 return isinstance(project, t) | |
76 return [d for d in deps if typeFilter(d)] | |
77 | |
78 def get_jdk_deployed_dists(): | |
79 return [d.name for d in mx_graal._jdkDeployedDists] | |
80 | |
81 def update_list(li, elements): | |
82 for e in elements: | |
83 if e not in li: | |
84 li.append(e) | |
85 | |
86 def make_dist_rule(dist, mf): | |
87 def path_dist_relative(p): | |
88 return os.path.relpath(p, dist.suite.dir) | |
89 shortName = short_dist_name(dist.name) | |
90 jdkDeployedDists = get_jdk_deployed_dists() | |
91 jarPath = path_dist_relative(dist.path) | |
92 sourcesVariableName = shortName + "_SRC" | |
93 depJarVariableName = shortName + "_DEP_JARS" | |
94 sources = [] | |
95 resources = [] | |
96 sortedDeps = dist.sorted_deps(True, transitive=False, includeAnnotationProcessors=True) | |
97 projects = filter_projects(sortedDeps, mx.Project) | |
98 targetPathPrefix = "$(TARGET)" + os.path.sep | |
99 libraryDeps = [path_dist_relative(l.get_path(False)) for l in filter_projects(sortedDeps, mx.Library)] | |
100 | |
101 annotationProcessorDeps = [] | |
102 distDeps = dist.get_dist_deps(includeSelf=False, transitive=True) | |
103 distDepProjects = [] | |
104 for d in distDeps: | |
105 update_list(distDepProjects, d.sorted_deps(includeLibs=False, transitive=True)) | |
106 | |
107 classPath = [targetPathPrefix + path_dist_relative(d.path) for d in distDeps] + libraryDeps \ | |
108 + [path_dist_relative(mx.dependency(name).path) for name in dist.excludedDependencies] | |
109 for p in projects: | |
110 if p.definedAnnotationProcessors != None and p.definedAnnotationProcessorsDist != dist: | |
111 update_list(annotationProcessorDeps, [p]) | |
112 for p in projects: | |
113 projectDir = path_dist_relative(p.dir) | |
114 if p not in distDepProjects and p not in annotationProcessorDeps: | |
115 for src in [projectDir + os.path.sep + d for d in p.srcDirs]: | |
116 sources.append("$(shell find {} -type f 2> /dev/null)".format(src)) | |
117 metaInf = src + os.path.sep + "META-INF" | |
118 if os.path.exists(metaInf): | |
119 resources.append(metaInf) | |
120 | |
121 | |
122 sourceLines = sourcesVariableName + " = " + ("\n" + sourcesVariableName + " += ").join(sources) | |
123 apPaths = [] | |
124 apDistNames = [] | |
125 apDistVariableNames = [] | |
126 for p in annotationProcessorDeps: | |
127 apPaths.append(path_dist_relative(p.definedAnnotationProcessorsDist.path)) | |
128 name = short_dist_name(p.definedAnnotationProcessorsDist.name) | |
129 apDistNames.append(name) | |
130 apDistVariableNames.append("$(" + name + "_JAR)") | |
131 shouldExport = dist.name in jdkDeployedDists | |
132 props = { | |
133 "name": shortName, | |
134 "jarPath": targetPathPrefix + jarPath, | |
135 "depJarsVariableAccess": "$(" + depJarVariableName + ")" if len(classPath) > 0 else "", | |
136 "depJarsVariable": depJarVariableName, | |
137 "sourceLines": sourceLines, | |
138 "sourcesVariableName": sourcesVariableName, | |
139 "annotationProcessors": " ".join(apDistVariableNames), | |
140 "cpAnnotationProcessors": ":".join(apDistVariableNames), | |
141 "jarDeps": " ".join(classPath), | |
142 "copyResources": " ".join(resources) | |
143 } | |
144 | |
145 mf.add_definition(sourceLines) | |
146 mf.add_definition("{name}_JAR = {jarPath}".format(**props)) | |
147 if len(classPath) > 0: mf.add_definition("{depJarsVariable} = {jarDeps}".format(**props)) | |
148 if shouldExport: mf.add_definition("EXPORTED_FILES += $({name}_JAR)".format(**props)) | |
149 mf.add_rule("""$({name}_JAR): $({sourcesVariableName}) {annotationProcessors} {depJarsVariableAccess} | |
150 \t$(call build_and_jar,{cpAnnotationProcessors},$(subst $(space),:,{depJarsVariableAccess}),{copyResources},$({name}_JAR)) | |
151 """.format(**props)) | |
152 return | |
153 | |
154 | |
155 | |
156 def do_build_makefile(mf, selectedDists, commandline): | |
157 java = mx.java() | |
158 bootClassPath = java.bootclasspath() | |
159 bootClassPath = bootClassPath.replace(os.path.realpath(java.jdk), "$(ABS_BOOTDIR)") | |
160 jdkBootClassPathVariableName = "JDK_BOOTCLASSPATH" | |
161 | |
162 mf.add_definition("""# This Makefile is generated automatically, do not edit | |
163 | |
164 TARGET=. | |
165 # Bootstrap JDK to be used (for javac and jar) | |
166 ABS_BOOTDIR= | |
167 | |
168 JAVAC=$(ABS_BOOTDIR)/bin/javac -g -target """ + str(java.javaCompliance) + """ | |
169 JAR=$(ABS_BOOTDIR)/bin/jar | |
170 | |
171 HS_COMMON_SRC=. | |
172 | |
173 # Directories, where the generated property-files reside within the JAR files | |
174 PROVIDERS_INF=/META-INF/jvmci.providers | |
175 SERVICES_INF=/META-INF/jvmci.services | |
176 OPTIONS_INF=/META-INF/jvmci.options | |
177 | |
178 JARS = $(foreach dist,$(DISTRIBUTIONS),$($(dist)_JAR)) | |
179 | |
180 ifeq ($(ABS_BOOTDIR),) | |
181 $(error Variable ABS_BOOTDIR must be set to a JDK installation.) | |
182 endif | |
183 ifeq ($(MAKE_VERBOSE),) | |
184 QUIETLY=@ | |
185 endif | |
186 | |
187 # Required to construct a whitespace for use with subst | |
188 space := | |
189 space += | |
190 | |
191 # Takes the provider files created by ServiceProviderProcessor (the processor | |
192 # for the @ServiceProvider annotation) and merges them into a single file. | |
193 # Arguments: | |
194 # 1: directory with contents of the JAR file | |
195 define process_providers | |
196 $(eval providers := $(1)/$(PROVIDERS_INF)) | |
197 $(eval services := $(1)/$(SERVICES_INF)) | |
198 $(QUIETLY) test -d $(services) || mkdir -p $(services) | |
199 $(QUIETLY) test ! -d $(providers) || (cd $(providers) && for i in $$(ls); do c=$$(cat $$i); echo $$i >> $(abspath $(services))/$$c; rm $$i; done) | |
200 | |
201 @# Since all projects are built together with one javac call we cannot determine | |
202 @# which project contains HotSpotVMConfig.inline.hpp so we hardcode it. | |
203 $(eval vmconfig := $(1)/hotspot/HotSpotVMConfig.inline.hpp) | |
204 $(eval vmconfigDest := $(HS_COMMON_SRC)/../jvmci/com.oracle.jvmci.hotspot/src_gen/hotspot) | |
205 $(QUIETLY) test ! -f $(vmconfig) || (mkdir -p $(vmconfigDest) && cp $(vmconfig) $(vmconfigDest)) | |
206 endef | |
207 | |
208 # Reads the files in jvmci.options/ created by OptionProcessor (the processor for the @Option annotation) | |
209 # and appends to services/com.oracle.jvmci.options.Options entries for the providers | |
210 # also created by the same processor. | |
211 # Arguments: | |
212 # 1: directory with contents of the JAR file | |
213 define process_options | |
214 $(eval options := $(1)/$(OPTIONS_INF)) | |
215 $(eval services := $(1)/META-INF/services) | |
216 $(QUIETLY) test -d $(services) || mkdir -p $(services) | |
217 $(QUIETLY) test ! -d $(options) || (cd $(options) && for i in $$(ls); do echo $${i}_Options >> $(abspath $(services))/com.oracle.jvmci.options.Options; done) | |
218 endef | |
219 | |
220 # Extracts META-INF/jvmci.services and META-INF/jvmci.options of a JAR file into a given directory | |
221 # Arguments: | |
222 # 1: JAR file to extract | |
223 # 2: target directory (which already exists) | |
224 define extract | |
225 $(eval TMP := $(shell mktemp -d $(TARGET)/tmp_XXXXX)) | |
226 $(QUIETLY) cd $(TMP) && $(JAR) xf $(abspath $(1)) && \\ | |
227 ((test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2))) && \\ | |
228 (test ! -d .$(OPTIONS_INF) || cp -r .$(OPTIONS_INF) $(abspath $(2)))); | |
229 $(QUIETLY) rm -r $(TMP); | |
230 $(QUIETLY) cp $(1) $(2) | |
231 endef | |
232 | |
233 # Calls $(JAVAC) with the boot class path $(JDK_BOOTCLASSPATH) and sources taken from the automatic variable $^ | |
234 # Arguments: | |
235 # 1: processorpath | |
236 # 2: classpath | |
237 # 3: resources to copy | |
238 # 4: target JAR file | |
239 define build_and_jar | |
240 $(info Building $(4)) | |
241 $(eval TMP := $(shell mkdir -p $(TARGET) && mktemp -d $(TARGET)/tmp_XXXXX)) | |
242 $(QUIETLY) $(JAVAC) -d $(TMP) -processorpath :$(1) -bootclasspath $(JDK_BOOTCLASSPATH) -cp :$(2) $(filter %.java,$^) | |
243 $(QUIETLY) test "$(3)" = "" || cp -r $(3) $(TMP) | |
244 $(QUIETLY) $(call process_options,$(TMP)) | |
245 $(QUIETLY) $(call process_providers,$(TMP)) | |
246 $(QUIETLY) mkdir -p $(shell dirname $(4)) | |
247 $(QUIETLY) $(JAR) -0cf $(4) -C $(TMP) . | |
248 $(QUIETLY) rm -r $(TMP) | |
249 endef | |
250 | |
251 # Verifies that make/defs.make contains an appropriate line for each JVMCI service or option | |
252 # and that only existing JVMCI services and options are exported. | |
253 # Arguments: | |
254 # 1: list of service or option files | |
255 # 2: variable name for directory of service or option files | |
256 define verify_defs_make | |
257 $(eval defs := make/defs.make) | |
258 $(eval uncondPattern := EXPORT_LIST += $$$$($(2))/) | |
259 $(eval condPattern := CONDITIONAL_EXPORT_LIST += $$$$($(2))/) | |
260 $(eval unconditionalExports := $(shell grep '^EXPORT_LIST += $$($2)' make/defs.make | sed 's:.*($(2))/::g')) | |
261 $(eval conditionalExports := $(shell grep '^CONDITIONAL_EXPORT_LIST += $$($2)' make/defs.make | sed 's:.*($(2))/::g')) | |
262 $(eval allExports := $(unconditionalExports) $(conditionalExports)) | |
263 $(foreach file,$(1),$(if $(findstring $(file),$(allExports)), ,$(error "Line matching '$(uncondPattern)$(file)' or '$(condPattern)$(file)' not found in $(defs)"))) | |
264 $(foreach export,$(unconditionalExports),$(if $(findstring $(export),$(1)), ,$(error "The line '$(uncondPattern)$(export)' should not be in $(defs)"))) | |
265 endef | |
266 | |
267 all: default | |
268 \t$(info Put $(EXPORTED_FILES) into SHARED_DIR $(SHARED_DIR)) | |
269 \t$(shell mkdir -p $(SHARED_DIR)) | |
270 \t$(foreach export,$(EXPORTED_FILES),$(call extract,$(export),$(SHARED_DIR))) | |
271 | |
272 export: all | |
273 \t$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.services/*)),EXPORT_JRE_LIB_JVMCI_SERVICES_DIR) | |
274 \t$(call verify_defs_make,$(notdir $(wildcard $(SHARED_DIR)/jvmci.options/*)),EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR) | |
275 .PHONY: export | |
276 | |
277 clean: | |
278 \t$(QUIETLY) rm $(JARS) 2> /dev/null || true | |
279 \t$(QUIETLY) rmdir -p $(dir $(JARS)) 2> /dev/null || true | |
280 .PHONY: export clean | |
281 | |
282 """) | |
283 s = mx.suite("graal") | |
284 dists = [] | |
285 ap = [] | |
286 projects = [] | |
287 for d in s.dists: | |
288 if d.name in selectedDists: | |
289 update_list(dists, d.get_dist_deps(True, True)) | |
290 update_list(projects, d.sorted_deps(includeLibs=False, transitive=True)) | |
291 | |
292 for p in projects: | |
293 deps = p.all_deps([], False, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=True) | |
294 for d in deps: | |
295 if d.definedAnnotationProcessorsDist != None: | |
296 apd = d.definedAnnotationProcessorsDist | |
297 update_list(ap, [apd]) | |
298 | |
299 if len(dists) > 0: | |
300 mf.add_definition(jdkBootClassPathVariableName + " = " + bootClassPath) | |
301 for d in ap: make_dist_rule(d, mf) | |
302 for d in dists: make_dist_rule(d, mf) | |
303 mf.add_definition("DISTRIBUTIONS = " + " ".join([short_dist_name(d.name) for d in dists+ap])) | |
304 mf.add_rule("default: $({}_JAR)\n.PHONY: default\n".format("_JAR) $(".join([short_dist_name(d.name) for d in dists]))) | |
305 return True | |
306 else: | |
307 for d in dists: | |
308 selectedDists.remove(d.name) | |
309 print "Distribution(s) '" + "', '".join(selectedDists) + "' does not exist." |