Mercurial > hg > truffle
comparison mx/mx_graal_makefile.py @ 21717:a3315bce5192
Change makefile generator to produce human readable code (JBS:GRAAL-52)
author | Stefan Anzinger <stefan.anzinger@oracle.com> |
---|---|
date | Wed, 03 Jun 2015 20:24:04 +0200 |
parents | 93d486d51ab4 |
children | b5bbf03bc17a |
comparison
equal
deleted
inserted
replaced
21716:2f9e4d984d16 | 21717:a3315bce5192 |
---|---|
1 import mx, os, sys | |
2 # | 1 # |
3 # ---------------------------------------------------------------------------------------------------- | 2 # ---------------------------------------------------------------------------------------------------- |
4 # | 3 # |
5 # Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. | 4 # Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. |
6 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
23 # or visit www.oracle.com if you need additional information or have any | 22 # or visit www.oracle.com if you need additional information or have any |
24 # questions. | 23 # questions. |
25 # | 24 # |
26 # ---------------------------------------------------------------------------------------------------- | 25 # ---------------------------------------------------------------------------------------------------- |
27 # | 26 # |
28 | 27 import mx, 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 | |
29 | 45 |
30 def build_makefile(args): | 46 def build_makefile(args): |
31 """Build a Makefile from the suitte.py to build graa.jar without python""" | 47 """Creates a Makefile which is able to build distributions without mx""" |
32 if len(args) == 0 or args[0] == "-": | 48 parser = ArgumentParser(prog='mx makefile') |
33 do_build_makefile(lambda l: sys.stdout.write(l + os.linesep)) | 49 parser.add_argument('-o', action='store', dest='output', help='Write contents to this file.') |
34 elif args[0] == "-o": | 50 parser.add_argument('selectedDists', help="Selected distribution names which are going to be built with make.", nargs=REMAINDER) |
35 with open(args[1], "w") as f: | 51 args = parser.parse_args(args) |
36 do_build_makefile(lambda l: f.write(l + os.linesep)) | 52 |
37 | 53 if args.selectedDists == None or len(args.selectedDists) == 0: |
38 def relative_dep_path(d): | 54 parser.print_help() |
39 if isinstance(d, str): d = mx.dependency(d) | 55 return |
40 return os.path.basename(d.get_path(False)) | 56 mf = Makefile() |
41 | 57 if do_build_makefile(mf, args.selectedDists): |
42 def createMakeRule(p, bootClasspath): | 58 contents = mf.generate() |
43 def filterDeps(deps, t): | 59 if args.output == None: |
44 def typeFilter(project): # filters | 60 print contents |
45 if isinstance(project, str): | 61 else: |
46 project = mx.dependency(project, True) | 62 with open(args.output, "w") as f: |
47 return isinstance(project, t) | 63 f.write(contents) |
48 return [d for d in deps if typeFilter(d)] | 64 |
49 | 65 |
50 | 66 def filter_projects(deps, t): |
51 canonicalDeps = p.canonical_deps() | 67 def typeFilter(project): # filters |
52 canonicalProjectDep = filterDeps(canonicalDeps, mx.Project) | 68 if isinstance(project, str): |
53 canonicalProjectDepDirs = ['$(TARGET)/' +i for i in canonicalProjectDep] | 69 project = mx.dependency(project, True) |
54 canonicalLibDep = filterDeps(canonicalDeps, mx.Library) | 70 return isinstance(project, t) |
55 canonicalLibDepJars = ["$(LIB)/" + relative_dep_path(d) for d in canonicalLibDep] | 71 return [d for d in deps if typeFilter(d)] |
56 | 72 |
57 allDep = p.all_deps([], True, False, includeAnnotationProcessors=True) | 73 |
58 allProcessorDistNames = [x.definedAnnotationProcessorsDist.name for x in filterDeps(allDep, mx.Project) if x.definedAnnotationProcessors != None] | 74 def make_dist_rule(dist, mf, bootClassPath=None): |
59 allProjectDep = filterDeps(allDep, mx.Project) | 75 def path_dist_relative(p): |
60 allProjectDepDir = ['$(TARGET)/' +i.name for i in allProjectDep] | 76 return os.path.relpath(p, dist.suite.dir) |
61 allLibDep = filterDeps(allDep, mx.Library) | 77 jarPath = path_dist_relative(dist.path) |
62 allLibDepJar = ["$(LIB)/" + relative_dep_path(d) for d in allLibDep] | 78 sourcesVariableName = dist.name + "_SRC" |
63 | 79 depJarVariableName = dist.name + "_DEP_JARS"; |
64 processor = p.annotation_processors_path() | 80 sources = [] |
65 if processor != None: processor = processor.replace(p.suite.dir, "$(TARGET)") | 81 resources = [] |
66 | 82 sortedDeps = dist.sorted_deps(True, transitive=False, includeAnnotationProcessors=True) |
67 cp = allLibDepJar +allProjectDepDir | 83 projects = filter_projects(sortedDeps, mx.Project) |
84 targetPathPrefix = "$(TARGET)" + os.path.sep | |
85 libraryDeps = [path_dist_relative(l.get_path(False)) for l in filter_projects(sortedDeps, mx.Library)] | |
86 | |
87 annotationProcessorDeps = set() | |
88 distDeps = dist.get_dist_deps(includeSelf=False, transitive=True) | |
89 distDepProjects = set() | |
90 for d in distDeps: | |
91 distDepProjects.update(d.sorted_deps(includeLibs=False, transitive=True)) | |
92 classPath = [targetPathPrefix + path_dist_relative(d.path) for d in distDeps] + libraryDeps | |
93 | |
94 for p in projects: | |
95 if p.definedAnnotationProcessors != None and p.definedAnnotationProcessorsDist != dist: | |
96 annotationProcessorDeps.add(p) | |
97 for p in projects: | |
98 projectDir = path_dist_relative(p.dir) | |
99 if p not in distDepProjects and p not in annotationProcessorDeps: | |
100 generatedSource = [path_dist_relative(p.source_gen_dir())] if len(annotationProcessorDeps) > 0 else [] | |
101 | |
102 for d in p.srcDirs + generatedSource: | |
103 src = projectDir + os.path.sep + d | |
104 sources.append("$(shell find {} -type file -name *.java 2> /dev/null)".format(src)) | |
105 metaInf = src + os.path.sep + "META-INF"; | |
106 if os.path.exists(metaInf): | |
107 resources.append(metaInf) | |
108 | |
109 | |
110 sourceLines = sourcesVariableName + " = " + ("\n" + sourcesVariableName + " += ").join(sources) | |
111 annotationProcessorPaths = [] | |
112 annotationProcessorDistNames = [] | |
113 annotationProcessorDistVariableNames = [] | |
114 for p in annotationProcessorDeps: | |
115 annotationProcessorPaths.append(path_dist_relative(p.definedAnnotationProcessorsDist.path)) | |
116 name = p.definedAnnotationProcessorsDist.name | |
117 annotationProcessorDistNames.append(name) | |
118 annotationProcessorDistVariableNames.append("$(" + name + "_JAR)") | |
119 | |
68 props = { | 120 props = { |
69 'name': p.name, | 121 "name": dist.name, |
70 'project_deps': ' '.join(canonicalProjectDepDirs + canonicalLibDepJars + allProcessorDistNames), | 122 "jarPath": targetPathPrefix + jarPath, |
71 'cp_deps': ('-cp ' + ':'.join(cp)) if len(cp) > 0 else '', | 123 "depends": "", |
72 'cp_boot': ('-bootclasspath ' + bootClasspath) if len(bootClasspath) > 0 else '', | 124 "depJarsVariableAccess": "$(" + depJarVariableName + ")" if len(classPath) > 0 else "", |
73 'processor': ('-processorpath ' + processor) if processor != None else '' | 125 "depJarsVariable": depJarVariableName, |
74 } | 126 "sourceLines": sourceLines, |
75 return """$(TARGET)/{name}: $(shell find graal/{name}/src/ -type f -name *.java) {project_deps} | 127 "sourcesVariableName": sourcesVariableName, |
128 "annotationProcessors": " ".join(annotationProcessorDistVariableNames), | |
129 "cpAnnotationProcessors": "-processorpath " + ":".join(annotationProcessorDistVariableNames) if len(annotationProcessorDistVariableNames) > 0 else "", | |
130 "bootCp": ("-bootclasspath " + bootClassPath) if bootClassPath != None else "", | |
131 "cpDeps": ("-cp " + ":".join(classPath)) if len(classPath) > 0 else "", | |
132 "jarDeps": " ".join(classPath), | |
133 "copyResources": "cp -r {} $(TMP)".format(" ".join(resources)) if len(resources) > 0 else "", | |
134 "targetPathPrefix": targetPathPrefix | |
135 } | |
136 | |
137 mf.add_definition(sourceLines) | |
138 mf.add_definition("{name}_JAR = {jarPath}".format(**props)) | |
139 if len(classPath) > 0: mf.add_definition("{depJarsVariable} = {jarDeps}".format(**props)) | |
140 mf.add_rule("""$({name}_JAR): $({sourcesVariableName}) {annotationProcessors} {depJarsVariableAccess} $(TARGET)/build | |
76 \t$(eval TMP := $(shell mktemp -d)) | 141 \t$(eval TMP := $(shell mktemp -d)) |
77 \ttest ! -d $(TARGET)/{name} || cp -Rp $(TARGET)/{name} $(TMP) | 142 \t$(JAVAC) -d $(TMP) {cpAnnotationProcessors} {bootCp} {cpDeps} $({sourcesVariableName}) |
78 \t$(JAVAC) -d $(TMP) {cp_boot} {processor} {cp_deps} $(shell find graal/{name}/src/ -type f -name *.java) | 143 \t{copyResources} |
79 \ttest ! -d graal/{name}/src/META-INF || (mkdir -p $(TARGET)/{name}/META-INF/ && cp -r graal/{name}/src/META-INF/ $(TARGET)/{name}/) | 144 \t$(call process_options,$(TMP)) |
80 \tmkdir -p $(TARGET)/{name} | 145 \tmkdir -p $$(dirname $({name}_JAR)) |
81 \tcp -r $(TMP)/* $(TARGET)/{name} | 146 \t$(JAR) cf $({name}_JAR) -C $(TMP) . |
82 \ttouch $(TARGET)/{name} | 147 \trm -r $(TMP)""".format(**props)) |
83 \trm -r $(TMP) | 148 return |
84 """.format(**props) | 149 |
85 | 150 |
86 def createDistributionRule(dist): | 151 def do_build_makefile(mf, selectedDists): |
87 sorted_deps = set(dist.sorted_deps(False, True)) | 152 java = mx.java() |
88 depDirs = ' '.join(['$(TARGET)/' + i.name for i in sorted_deps]) | 153 bootClassPath = java.bootclasspath() |
89 depDirsStar = ' '.join(['$(TARGET)/' + i.name + '/*' for i in sorted_deps]) | 154 bootClassPath = bootClassPath.replace(java.jdk, "$(JDK)") |
90 jarPath = os.path.relpath(dist.path, dist.suite.dir) | 155 jdkBootClassPathVariableName = "JDK_BOOTCLASSPATH" |
91 jarDir = os.path.dirname(jarPath) | 156 |
92 props = { | 157 mf.add_definition("""VERBOSE= |
93 'dist_name': dist.name, | 158 TARGET=. |
94 'depDirs': depDirs, | |
95 'depDirsStar': depDirsStar, | |
96 'jar_path': jarPath, | |
97 'jar_dir': jarDir, | |
98 'providers_dir': '$(TMP)/META-INF/providers/ ', | |
99 'services_dir': '$(TMP)/META-INF/services/' | |
100 } | |
101 return """{dist_name}: {depDirs} | |
102 \t$(eval TMP := $(shell mktemp -d)) | |
103 \tmkdir -p $(TARGET){jar_dir} | |
104 \ttouch $(TARGET)/{jar_path} | |
105 \tcp -r {depDirsStar} $(TMP) | |
106 \ttest -d {services_dir} || mkdir -p {services_dir} | |
107 \ttest ! -d {providers_dir} || (cd {providers_dir} && for i in $$(ls); do c=$$(cat $$i); echo $$i >> {services_dir}$$c; done) | |
108 \ttest ! -d {providers_dir} || rm -r {providers_dir} | |
109 \t$(JAR) cvf $(TARGET){jar_path} -C $(TMP) . | |
110 \trm -r $(TMP) | |
111 """.format(**props) | |
112 | |
113 def createDownloadRule(lib): | |
114 http_urls = [u for u in lib.urls if u.startswith("http")] | |
115 if len(http_urls) == 0: http_urls = [u for u in lib.urls if u.startswith("jar")] | |
116 if len(http_urls) == 0: raise BaseException("No http url specified for downloading library %s: available urls: %s" % (lib.name, lib.urls)) | |
117 url = http_urls[0] | |
118 tofile = '$(LIB)/' + relative_dep_path(lib) | |
119 if url.startswith("jar"): | |
120 props = { | |
121 'url': url[url.find(":")+1:url.rfind("!")], | |
122 'archive_file': url[url.rfind("!")+1:], | |
123 'dest': tofile | |
124 } | |
125 dl = """\t$(eval TMP := $(shell mktemp -d)) | |
126 \tcd $(TMP) && $(WGET) -O dl.zip {url} && $(JAR) xf dl.zip | |
127 \tmv $(TMP)/{archive_file} {dest} | |
128 \trm -rf $(TMP)""".format(**props) | |
129 else: | |
130 dl = "\t$(WGET) -O {} {}".format(tofile, url) | |
131 return """{}:\n{}""".format(tofile, dl) | |
132 | |
133 | |
134 def create_suite_build(suite, out): | |
135 for p in suite.projects: | |
136 java = mx.java(p.javaCompliance) | |
137 bootClassPath = java.bootclasspath() | |
138 bootClassPath = bootClassPath.replace(java.jdk, "$(JDK)") | |
139 out(createMakeRule(p, bootClassPath)) | |
140 for l in suite.libs: | |
141 out(createDownloadRule(l)) | |
142 | |
143 distributionNames = [] | |
144 for d in suite.dists: | |
145 distributionNames.append(d.name) | |
146 out(createDistributionRule(d)) | |
147 out("{0}: {1}\n.PHONY: {1}".format(suite.name, " ".join(distributionNames))) | |
148 | |
149 | |
150 def do_build_makefile(out): | |
151 out("""VERBOSE= | |
152 TARGET=build/ | |
153 LIB=$(TARGET)/lib | |
154 JDK= | 159 JDK= |
155 | 160 |
156 WGET=wget | 161 WGET=wget |
157 JAVAC=$(JDK)/bin/javac | 162 JAVAC=$(JDK)/bin/javac -g -target """ + str(java.javaCompliance) + """ |
158 JAR=$(JDK)/bin/jar | 163 JAR=$(JDK)/bin/jar |
159 | 164 |
160 | 165 |
161 ifeq ($(JDK),) | 166 ifeq ($(JDK),) |
162 $(error Variable JDK must be set to a JDK installation.) | 167 $(error Variable JDK must be set to a JDK installation.) |
163 endif | 168 endif |
164 ifneq ($(VERBOSE),) | 169 ifneq ($(VERBOSE),) |
165 SHELL=sh -x | 170 SHELL=sh -x |
166 endif | 171 endif |
167 | 172 |
173 define process_options = | |
174 $(eval providers=$(1)/META-INF/providers/) | |
175 $(eval services=$(1)/META-INF/services/) | |
176 test -d $(services) || mkdir -p $(services) | |
177 test ! -d $(providers) || (cd $(providers) && for i in $$(ls $(providers)); do c=$$(cat $$i); echo $$i >> $(services)$$c; rm $$i; done) | |
178 endef | |
179 | |
168 all: default | 180 all: default |
169 | 181 |
170 $(TARGET): | 182 $(TARGET)/build: |
171 \tmkdir -p $(TARGET) | 183 \tmkdir -p $(TARGET)/build |
172 | 184 |
173 $(LIB): | 185 $(LIB): |
174 \tmkdir -p $(LIB) | 186 \tmkdir -p $(LIB) |
175 """) | 187 """) |
176 suiteNames = [] | 188 s = mx.suite("graal") |
177 for s in mx.suites(): | 189 dists = set() |
178 suiteNames.append(s.name) | 190 ap = set() |
179 create_suite_build(s, out) | 191 projects = set() |
180 | 192 |
181 out("""default: $(TARGET) $(LIB) {0} | 193 for d in s.dists: |
182 .PHONY: {0} | 194 if d.name in selectedDists: |
183 """.format(" ".join(suiteNames))) | 195 dists.update(d.get_dist_deps(True, True)) |
184 | 196 projects.update(d.sorted_deps(includeLibs=False, transitive=True)) |
197 for p in projects: | |
198 deps = p.all_deps([], False, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=True) | |
199 for d in deps: | |
200 if d.definedAnnotationProcessorsDist != None: | |
201 apd = d.definedAnnotationProcessorsDist | |
202 ap.add(apd) | |
203 | |
204 if len(dists) > 0: | |
205 mf.add_definition(jdkBootClassPathVariableName + " = " + bootClassPath) | |
206 bootClassPathVarAccess = "$(" + jdkBootClassPathVariableName + ")" | |
207 for d in ap: make_dist_rule(d, mf, bootClassPathVarAccess) | |
208 for d in dists: make_dist_rule(d, mf, bootClassPathVarAccess) | |
209 mf.add_rule("default: $({}_JAR)\n.PHONY: default".format("_JAR) $(".join([d.name for d in dists]))) | |
210 return True | |
211 else: | |
212 for d in dists: | |
213 selectedDists.remove(d.name) | |
214 print "Distribution(s) '" + "', '".join(selectedDists) + "' does not exist." | |
215 | |
216 | |
217 | |
218 | |
219 |